From da0c3910a3fe1008f37db52d02f00a73b1905c11 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Tue, 27 Oct 2020 19:23:15 +1000 Subject: [PATCH 001/152] modify vote type on proto --- proto/cosmos/gov/v1beta1/gov.proto | 6 +- x/gov/types/gov.pb.go | 307 ++++++++++++++++++----------- 2 files changed, 190 insertions(+), 123 deletions(-) diff --git a/proto/cosmos/gov/v1beta1/gov.proto b/proto/cosmos/gov/v1beta1/gov.proto index 1d72e643212c..3c00d4b2b2f6 100644 --- a/proto/cosmos/gov/v1beta1/gov.proto +++ b/proto/cosmos/gov/v1beta1/gov.proto @@ -119,9 +119,9 @@ message Vote { option (gogoproto.goproto_stringer) = false; option (gogoproto.equal) = false; - uint64 proposal_id = 1 [(gogoproto.moretags) = "yaml:\"proposal_id\""]; - string voter = 2; - VoteOption option = 3; + uint64 proposal_id = 1 [(gogoproto.moretags) = "yaml:\"proposal_id\""]; + string voter = 2; + repeated VoteOption options = 3; } // DepositParams defines the params for deposits on governance proposals. diff --git a/x/gov/types/gov.pb.go b/x/gov/types/gov.pb.go index 922186d01f0d..3028ae0c6d67 100644 --- a/x/gov/types/gov.pb.go +++ b/x/gov/types/gov.pb.go @@ -288,9 +288,9 @@ var xxx_messageInfo_TallyResult proto.InternalMessageInfo // Vote defines a vote on a governance proposal. // A Vote consists of a proposal ID, the voter, and the vote option. type Vote struct { - ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty" yaml:"proposal_id"` - Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` - Option VoteOption `protobuf:"varint,3,opt,name=option,proto3,enum=cosmos.gov.v1beta1.VoteOption" json:"option,omitempty"` + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty" yaml:"proposal_id"` + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` + Options []VoteOption `protobuf:"varint,3,rep,packed,name=options,proto3,enum=cosmos.gov.v1beta1.VoteOption" json:"options,omitempty"` } func (m *Vote) Reset() { *m = Vote{} } @@ -464,94 +464,94 @@ func init() { func init() { proto.RegisterFile("cosmos/gov/v1beta1/gov.proto", fileDescriptor_6e82113c1a9a4b7c) } var fileDescriptor_6e82113c1a9a4b7c = []byte{ - // 1377 bytes of a gzipped FileDescriptorProto + // 1380 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0x5f, 0x6c, 0xdb, 0xd4, - 0x17, 0x8e, 0xd3, 0xbf, 0xb9, 0x49, 0x5b, 0xef, 0x36, 0x6b, 0x53, 0xff, 0xf6, 0xb3, 0x8d, 0x41, - 0xa8, 0x9a, 0xb6, 0x74, 0x2b, 0x08, 0x44, 0x27, 0x21, 0x92, 0xc6, 0x63, 0x41, 0x53, 0x12, 0x39, - 0x5e, 0xa6, 0x8d, 0x07, 0xcb, 0x49, 0xee, 0x52, 0x43, 0xec, 0x1b, 0xe2, 0x9b, 0xd2, 0x88, 0x17, - 0x1e, 0xa7, 0x20, 0xa1, 0xbd, 0x31, 0x09, 0x45, 0x9a, 0xc4, 0x1b, 0xcf, 0x3c, 0xf3, 0x5c, 0x21, - 0x24, 0x26, 0x9e, 0x26, 0x90, 0x32, 0xd6, 0x49, 0x68, 0xea, 0x63, 0x1f, 0x78, 0x46, 0xf6, 0xbd, - 0x6e, 0x9c, 0xa4, 0xa2, 0x84, 0xa7, 0xd9, 0xe7, 0x9e, 0xef, 0xfb, 0xce, 0xfd, 0x7c, 0xce, 0xc9, - 0x0a, 0x2e, 0xd5, 0xb0, 0x6b, 0x63, 0x77, 0xab, 0x81, 0xf7, 0xb7, 0xf6, 0xaf, 0x57, 0x11, 0x31, - 0xaf, 0x7b, 0xcf, 0xe9, 0x56, 0x1b, 0x13, 0x0c, 0x21, 0x3d, 0x4d, 0x7b, 0x11, 0x76, 0x2a, 0x88, - 0x0c, 0x51, 0x35, 0x5d, 0x74, 0x0a, 0xa9, 0x61, 0xcb, 0xa1, 0x18, 0x21, 0xd9, 0xc0, 0x0d, 0xec, - 0x3f, 0x6e, 0x79, 0x4f, 0x2c, 0xba, 0x41, 0x51, 0x06, 0x3d, 0x60, 0xb4, 0xf4, 0x48, 0x6a, 0x60, - 0xdc, 0x68, 0xa2, 0x2d, 0xff, 0xad, 0xda, 0x79, 0xb0, 0x45, 0x2c, 0x1b, 0xb9, 0xc4, 0xb4, 0x5b, - 0x01, 0x76, 0x3c, 0xc1, 0x74, 0xba, 0xec, 0x48, 0x1c, 0x3f, 0xaa, 0x77, 0xda, 0x26, 0xb1, 0x30, - 0x2b, 0x46, 0xb9, 0x0b, 0x12, 0x3a, 0x3a, 0x20, 0xa5, 0x36, 0x6e, 0x61, 0xd7, 0x6c, 0xc2, 0x24, - 0x98, 0x23, 0x16, 0x69, 0xa2, 0x14, 0x27, 0x73, 0x9b, 0x31, 0x8d, 0xbe, 0x40, 0x19, 0xc4, 0xeb, - 0xc8, 0xad, 0xb5, 0xad, 0x96, 0x07, 0x4d, 0x45, 0xfd, 0xb3, 0x70, 0x68, 0x67, 0xe5, 0xd5, 0x13, - 0x89, 0xfb, 0xf5, 0x87, 0xab, 0x0b, 0xbb, 0xd8, 0x21, 0xc8, 0x21, 0xca, 0x2f, 0x1c, 0x58, 0xc8, - 0xa1, 0x16, 0x76, 0x2d, 0x02, 0xdf, 0x05, 0xf1, 0x16, 0x13, 0x30, 0xac, 0xba, 0x4f, 0x3d, 0x9b, - 0x5d, 0x3b, 0x19, 0x48, 0xb0, 0x6b, 0xda, 0xcd, 0x1d, 0x25, 0x74, 0xa8, 0x68, 0x20, 0x78, 0xcb, - 0xd7, 0xe1, 0x25, 0x10, 0xab, 0x53, 0x0e, 0xdc, 0x66, 0xaa, 0xc3, 0x00, 0xac, 0x81, 0x79, 0xd3, - 0xc6, 0x1d, 0x87, 0xa4, 0x66, 0xe4, 0x99, 0xcd, 0xf8, 0xf6, 0x46, 0x9a, 0xd9, 0xe6, 0x39, 0x1f, - 0x7c, 0x8e, 0xf4, 0x2e, 0xb6, 0x9c, 0xec, 0xb5, 0xc3, 0x81, 0x14, 0xf9, 0xfe, 0xb9, 0xb4, 0xd9, - 0xb0, 0xc8, 0x5e, 0xa7, 0x9a, 0xae, 0x61, 0x9b, 0x79, 0xcc, 0xfe, 0xb9, 0xea, 0xd6, 0x3f, 0xdd, - 0x22, 0xdd, 0x16, 0x72, 0x7d, 0x80, 0xab, 0x31, 0xea, 0x9d, 0xc5, 0x87, 0x4f, 0xa4, 0xc8, 0xab, - 0x27, 0x52, 0x44, 0xf9, 0x6b, 0x1e, 0x2c, 0x9e, 0xfa, 0xf4, 0xf6, 0x59, 0x57, 0x5a, 0x3d, 0x1e, - 0x48, 0x51, 0xab, 0x7e, 0x32, 0x90, 0x62, 0xf4, 0x62, 0xe3, 0xf7, 0xb9, 0x01, 0x16, 0x6a, 0xd4, - 0x1f, 0xff, 0x36, 0xf1, 0xed, 0x64, 0x9a, 0x7e, 0x9f, 0x74, 0xf0, 0x7d, 0xd2, 0x19, 0xa7, 0x9b, - 0x8d, 0xff, 0x34, 0x34, 0x52, 0x0b, 0x10, 0xb0, 0x02, 0xe6, 0x5d, 0x62, 0x92, 0x8e, 0x9b, 0x9a, - 0x91, 0xb9, 0xcd, 0xe5, 0x6d, 0x25, 0x3d, 0xd9, 0x7c, 0xe9, 0xa0, 0xc0, 0xb2, 0x9f, 0x99, 0x15, - 0x4e, 0x06, 0xd2, 0xda, 0x98, 0xc9, 0x94, 0x44, 0xd1, 0x18, 0x1b, 0x6c, 0x01, 0xf8, 0xc0, 0x72, - 0xcc, 0xa6, 0x41, 0xcc, 0x66, 0xb3, 0x6b, 0xb4, 0x91, 0xdb, 0x69, 0x92, 0xd4, 0xac, 0x5f, 0x9f, - 0x74, 0x96, 0x86, 0xee, 0xe5, 0x69, 0x7e, 0x5a, 0xf6, 0x35, 0xcf, 0xd8, 0x93, 0x81, 0xb4, 0x41, - 0x45, 0x26, 0x89, 0x14, 0x8d, 0xf7, 0x83, 0x21, 0x10, 0xfc, 0x18, 0xc4, 0xdd, 0x4e, 0xd5, 0xb6, - 0x88, 0xe1, 0x75, 0x72, 0x6a, 0xce, 0x97, 0x12, 0x26, 0xac, 0xd0, 0x83, 0x36, 0xcf, 0x8a, 0x4c, - 0x85, 0xf5, 0x4b, 0x08, 0xac, 0x3c, 0x7a, 0x2e, 0x71, 0x1a, 0xa0, 0x11, 0x0f, 0x00, 0x2d, 0xc0, - 0xb3, 0x16, 0x31, 0x90, 0x53, 0xa7, 0x0a, 0xf3, 0xe7, 0x2a, 0xbc, 0xce, 0x14, 0xd6, 0xa9, 0xc2, - 0x38, 0x03, 0x95, 0x59, 0x66, 0x61, 0xd5, 0xa9, 0xfb, 0x52, 0x0f, 0x39, 0xb0, 0x44, 0x30, 0x31, - 0x9b, 0x06, 0x3b, 0x48, 0x2d, 0x9c, 0xd7, 0x88, 0xb7, 0x98, 0x4e, 0x92, 0xea, 0x8c, 0xa0, 0x95, - 0xa9, 0x1a, 0x34, 0xe1, 0x63, 0x83, 0x11, 0x6b, 0x82, 0x0b, 0xfb, 0x98, 0x58, 0x4e, 0xc3, 0xfb, - 0xbc, 0x6d, 0x66, 0xec, 0xe2, 0xb9, 0xd7, 0x7e, 0x83, 0x95, 0x93, 0xa2, 0xe5, 0x4c, 0x50, 0xd0, - 0x7b, 0xaf, 0xd0, 0x78, 0xd9, 0x0b, 0xfb, 0x17, 0x7f, 0x00, 0x58, 0x68, 0x68, 0x71, 0xec, 0x5c, - 0x2d, 0x85, 0x69, 0xad, 0x8d, 0x68, 0x8d, 0x3a, 0xbc, 0x44, 0xa3, 0xcc, 0xe0, 0x9d, 0x59, 0x6f, - 0xab, 0x28, 0x87, 0x51, 0x10, 0x0f, 0xb7, 0xcf, 0x07, 0x60, 0xa6, 0x8b, 0x5c, 0xba, 0xa1, 0xb2, - 0x69, 0x8f, 0xf5, 0xb7, 0x81, 0xf4, 0xe6, 0xbf, 0x30, 0x2e, 0xef, 0x10, 0xcd, 0x83, 0xc2, 0x5b, - 0x60, 0xc1, 0xac, 0xba, 0xc4, 0xb4, 0xd8, 0x2e, 0x9b, 0x9a, 0x25, 0x80, 0xc3, 0xf7, 0x41, 0xd4, - 0xc1, 0xfe, 0x40, 0x4e, 0x4f, 0x12, 0x75, 0x30, 0x6c, 0x80, 0x84, 0x83, 0x8d, 0xcf, 0x2d, 0xb2, - 0x67, 0xec, 0x23, 0x82, 0xfd, 0xb1, 0x8b, 0x65, 0xd5, 0xe9, 0x98, 0x4e, 0x06, 0xd2, 0x2a, 0x35, - 0x35, 0xcc, 0xa5, 0x68, 0xc0, 0xc1, 0x77, 0x2d, 0xb2, 0x57, 0x41, 0x04, 0x33, 0x2b, 0xbf, 0xe1, - 0xc0, 0x6c, 0x05, 0x13, 0xf4, 0xdf, 0x57, 0x72, 0x12, 0xcc, 0xed, 0x63, 0x82, 0x82, 0x75, 0x4c, - 0x5f, 0xe0, 0x3b, 0x60, 0x1e, 0xd3, 0xdf, 0x06, 0xba, 0x9b, 0xc4, 0xb3, 0xf6, 0x86, 0x27, 0x5c, - 0xf4, 0xb3, 0x34, 0x96, 0xbd, 0xb3, 0xf8, 0x38, 0xd8, 0xae, 0x3f, 0x46, 0xc1, 0x12, 0x6b, 0xe6, - 0x92, 0xd9, 0x36, 0x6d, 0x17, 0x7e, 0xcb, 0x81, 0xb8, 0x6d, 0x39, 0xa7, 0xb3, 0xc5, 0x9d, 0x37, - 0x5b, 0x86, 0xe7, 0xda, 0xf1, 0x40, 0xba, 0x18, 0x42, 0x5d, 0xc1, 0xb6, 0x45, 0x90, 0xdd, 0x22, - 0xdd, 0xe1, 0xdd, 0x42, 0xc7, 0xd3, 0x8d, 0x1c, 0xb0, 0x2d, 0x27, 0x18, 0xb8, 0xaf, 0x39, 0x00, - 0x6d, 0xf3, 0x20, 0x20, 0x32, 0x5a, 0xa8, 0x6d, 0xe1, 0x3a, 0x5b, 0xeb, 0x1b, 0x13, 0x63, 0x90, - 0x63, 0x3f, 0xbb, 0xf4, 0xd3, 0x1e, 0x0f, 0xa4, 0x4b, 0x93, 0xe0, 0x91, 0x5a, 0xd9, 0x42, 0x9d, - 0xcc, 0x52, 0x1e, 0x7b, 0x83, 0xc2, 0xdb, 0xe6, 0x41, 0x60, 0x17, 0x0d, 0x7f, 0xc5, 0x81, 0x44, - 0xc5, 0x9f, 0x1e, 0xe6, 0xdf, 0x17, 0x80, 0x4d, 0x53, 0x50, 0x1b, 0x77, 0x5e, 0x6d, 0x37, 0x58, - 0x6d, 0xeb, 0x23, 0xb8, 0x91, 0xb2, 0x92, 0x23, 0xc3, 0x1b, 0xae, 0x28, 0x41, 0x63, 0xac, 0x9a, - 0xdf, 0x83, 0x99, 0x65, 0xc5, 0xdc, 0x07, 0xf3, 0x9f, 0x75, 0x70, 0xbb, 0x63, 0xfb, 0x55, 0x24, - 0xb2, 0xd9, 0x29, 0x3a, 0x3c, 0x87, 0x6a, 0xc7, 0x03, 0x89, 0xa7, 0xf8, 0x61, 0x35, 0x1a, 0x63, - 0x84, 0x35, 0x10, 0x23, 0x7b, 0x6d, 0xe4, 0xee, 0xe1, 0x26, 0xfd, 0x00, 0x89, 0xa9, 0x06, 0x88, - 0xd2, 0xaf, 0x9e, 0x52, 0x84, 0x14, 0x86, 0xbc, 0xb0, 0xc7, 0x81, 0x65, 0x6f, 0xaa, 0x8c, 0xa1, - 0xd4, 0x8c, 0x2f, 0x55, 0x9b, 0x5a, 0x2a, 0x35, 0xca, 0x33, 0xe2, 0xef, 0x45, 0xe6, 0xef, 0x48, - 0x86, 0xa2, 0x2d, 0x79, 0x01, 0x3d, 0x78, 0xbf, 0xfc, 0x27, 0x07, 0xc0, 0x70, 0x9a, 0xe0, 0x15, - 0xb0, 0x5e, 0x29, 0xea, 0xaa, 0x51, 0x2c, 0xe9, 0xf9, 0x62, 0xc1, 0xb8, 0x53, 0x28, 0x97, 0xd4, - 0xdd, 0xfc, 0xcd, 0xbc, 0x9a, 0xe3, 0x23, 0xc2, 0x4a, 0xaf, 0x2f, 0xc7, 0x69, 0xa2, 0xea, 0x89, - 0x40, 0x05, 0xac, 0x84, 0xb3, 0xef, 0xa9, 0x65, 0x9e, 0x13, 0x96, 0x7a, 0x7d, 0x39, 0x46, 0xb3, - 0xee, 0x21, 0x17, 0x5e, 0x06, 0xab, 0xe1, 0x9c, 0x4c, 0xb6, 0xac, 0x67, 0xf2, 0x05, 0x3e, 0x2a, - 0x5c, 0xe8, 0xf5, 0xe5, 0x25, 0x9a, 0x97, 0x61, 0x2b, 0x50, 0x06, 0xcb, 0xe1, 0xdc, 0x42, 0x91, - 0x9f, 0x11, 0x12, 0xbd, 0xbe, 0xbc, 0x48, 0xd3, 0x0a, 0x18, 0x6e, 0x83, 0xd4, 0x68, 0x86, 0x71, - 0x37, 0xaf, 0xdf, 0x32, 0x2a, 0xaa, 0x5e, 0xe4, 0x67, 0x85, 0x64, 0xaf, 0x2f, 0xf3, 0x41, 0x6e, - 0xb0, 0xaf, 0x84, 0xd9, 0x87, 0xdf, 0x89, 0x91, 0xcb, 0x3f, 0x47, 0xc1, 0xf2, 0xe8, 0x7f, 0x69, - 0x60, 0x1a, 0xfc, 0xaf, 0xa4, 0x15, 0x4b, 0xc5, 0x72, 0xe6, 0xb6, 0x51, 0xd6, 0x33, 0xfa, 0x9d, - 0xf2, 0xd8, 0x85, 0xfd, 0xab, 0xd0, 0xe4, 0x82, 0xd5, 0x84, 0x37, 0x80, 0x38, 0x9e, 0x9f, 0x53, - 0x4b, 0xc5, 0x72, 0x5e, 0x37, 0x4a, 0xaa, 0x96, 0x2f, 0xe6, 0x78, 0x4e, 0x58, 0xef, 0xf5, 0xe5, - 0x55, 0x0a, 0x19, 0x19, 0x2a, 0xf8, 0x1e, 0xf8, 0xff, 0x38, 0xb8, 0x52, 0xd4, 0xf3, 0x85, 0x0f, - 0x03, 0x6c, 0x54, 0x58, 0xeb, 0xf5, 0x65, 0x48, 0xb1, 0x95, 0xd0, 0x04, 0xc0, 0x2b, 0x60, 0x6d, - 0x1c, 0x5a, 0xca, 0x94, 0xcb, 0x6a, 0x8e, 0x9f, 0x11, 0xf8, 0x5e, 0x5f, 0x4e, 0x50, 0x4c, 0xc9, - 0x74, 0x5d, 0x54, 0x87, 0xd7, 0x40, 0x6a, 0x3c, 0x5b, 0x53, 0x3f, 0x52, 0x77, 0x75, 0x35, 0xc7, - 0xcf, 0x0a, 0xb0, 0xd7, 0x97, 0x97, 0x69, 0xbe, 0x86, 0x3e, 0x41, 0x35, 0x82, 0xce, 0xe4, 0xbf, - 0x99, 0xc9, 0xdf, 0x56, 0x73, 0xfc, 0x5c, 0x98, 0xff, 0xa6, 0x69, 0x35, 0x51, 0x9d, 0xda, 0x99, - 0x2d, 0x1c, 0xbe, 0x10, 0x23, 0xcf, 0x5e, 0x88, 0x91, 0x2f, 0x8f, 0xc4, 0xc8, 0xe1, 0x91, 0xc8, - 0x3d, 0x3d, 0x12, 0xb9, 0x3f, 0x8e, 0x44, 0xee, 0xd1, 0x4b, 0x31, 0xf2, 0xf4, 0xa5, 0x18, 0x79, - 0xf6, 0x52, 0x8c, 0xdc, 0xff, 0xe7, 0x85, 0x78, 0xe0, 0xff, 0x29, 0xe4, 0xf7, 0x73, 0x75, 0xde, - 0xdf, 0x21, 0x6f, 0xfd, 0x1d, 0x00, 0x00, 0xff, 0xff, 0xef, 0x91, 0x01, 0x67, 0x25, 0x0d, 0x00, - 0x00, + 0x17, 0x8e, 0xd3, 0xff, 0x37, 0x69, 0xea, 0xdd, 0x66, 0x6d, 0xea, 0xdf, 0x7e, 0xb6, 0x31, 0x08, + 0x55, 0xd3, 0x96, 0x6e, 0x05, 0x09, 0xe8, 0x24, 0x44, 0xd2, 0x78, 0x2c, 0x68, 0x4a, 0x22, 0xc7, + 0xcb, 0xb4, 0xf1, 0x60, 0x39, 0xc9, 0x5d, 0x6a, 0x88, 0x7d, 0x43, 0x7c, 0x53, 0x1a, 0xf1, 0xc2, + 0xe3, 0x14, 0x24, 0xb4, 0xc7, 0x21, 0x14, 0x69, 0x12, 0x6f, 0x3c, 0xf3, 0xcc, 0x73, 0x85, 0x90, + 0x98, 0x78, 0x9a, 0x40, 0xca, 0x58, 0x27, 0xa1, 0xa9, 0x8f, 0x7d, 0xe0, 0x19, 0xd9, 0xf7, 0xba, + 0x71, 0x92, 0x8a, 0x12, 0x9e, 0x66, 0x9f, 0x7b, 0xbe, 0xef, 0x3b, 0xf7, 0xf3, 0x39, 0x27, 0x2b, + 0xb8, 0x54, 0xc3, 0xae, 0x8d, 0xdd, 0xad, 0x06, 0xde, 0xdf, 0xda, 0xbf, 0x5e, 0x45, 0xc4, 0xbc, + 0xee, 0x3d, 0xa7, 0x5b, 0x6d, 0x4c, 0x30, 0x84, 0xf4, 0x34, 0xed, 0x45, 0xd8, 0xa9, 0x20, 0x32, + 0x44, 0xd5, 0x74, 0xd1, 0x29, 0xa4, 0x86, 0x2d, 0x87, 0x62, 0x84, 0x64, 0x03, 0x37, 0xb0, 0xff, + 0xb8, 0xe5, 0x3d, 0xb1, 0xe8, 0x06, 0x45, 0x19, 0xf4, 0x80, 0xd1, 0xd2, 0x23, 0xa9, 0x81, 0x71, + 0xa3, 0x89, 0xb6, 0xfc, 0xb7, 0x6a, 0xe7, 0xc1, 0x16, 0xb1, 0x6c, 0xe4, 0x12, 0xd3, 0x6e, 0x05, + 0xd8, 0xf1, 0x04, 0xd3, 0xe9, 0xb2, 0x23, 0x71, 0xfc, 0xa8, 0xde, 0x69, 0x9b, 0xc4, 0xc2, 0xac, + 0x18, 0xe5, 0x2e, 0x88, 0xeb, 0xe8, 0x80, 0x94, 0xda, 0xb8, 0x85, 0x5d, 0xb3, 0x09, 0x93, 0x60, + 0x8e, 0x58, 0xa4, 0x89, 0x52, 0x9c, 0xcc, 0x6d, 0x2e, 0x69, 0xf4, 0x05, 0xca, 0x20, 0x56, 0x47, + 0x6e, 0xad, 0x6d, 0xb5, 0x3c, 0x68, 0x2a, 0xea, 0x9f, 0x85, 0x43, 0x3b, 0x2b, 0xaf, 0x9e, 0x48, + 0xdc, 0xaf, 0x3f, 0x5c, 0x5d, 0xd8, 0xc5, 0x0e, 0x41, 0x0e, 0x51, 0x7e, 0xe1, 0xc0, 0x42, 0x0e, + 0xb5, 0xb0, 0x6b, 0x11, 0xf8, 0x0e, 0x88, 0xb5, 0x98, 0x80, 0x61, 0xd5, 0x7d, 0xea, 0xd9, 0xec, + 0xda, 0xc9, 0x40, 0x82, 0x5d, 0xd3, 0x6e, 0xee, 0x28, 0xa1, 0x43, 0x45, 0x03, 0xc1, 0x5b, 0xbe, + 0x0e, 0x2f, 0x81, 0xa5, 0x3a, 0xe5, 0xc0, 0x6d, 0xa6, 0x3a, 0x0c, 0xc0, 0x1a, 0x98, 0x37, 0x6d, + 0xdc, 0x71, 0x48, 0x6a, 0x46, 0x9e, 0xd9, 0x8c, 0x6d, 0x6f, 0xa4, 0x99, 0x6d, 0x9e, 0xf3, 0xc1, + 0xe7, 0x48, 0xef, 0x62, 0xcb, 0xc9, 0x5e, 0x3b, 0x1c, 0x48, 0x91, 0xef, 0x9f, 0x4b, 0x9b, 0x0d, + 0x8b, 0xec, 0x75, 0xaa, 0xe9, 0x1a, 0xb6, 0x99, 0xc7, 0xec, 0x9f, 0xab, 0x6e, 0xfd, 0xd3, 0x2d, + 0xd2, 0x6d, 0x21, 0xd7, 0x07, 0xb8, 0x1a, 0xa3, 0xde, 0x59, 0x7c, 0xf8, 0x44, 0x8a, 0xbc, 0x7a, + 0x22, 0x45, 0x94, 0xbf, 0xe6, 0xc1, 0xe2, 0xa9, 0x4f, 0x6f, 0x9f, 0x75, 0xa5, 0xd5, 0xe3, 0x81, + 0x14, 0xb5, 0xea, 0x27, 0x03, 0x69, 0x89, 0x5e, 0x6c, 0xfc, 0x3e, 0x37, 0xc0, 0x42, 0x8d, 0xfa, + 0xe3, 0xdf, 0x26, 0xb6, 0x9d, 0x4c, 0xd3, 0xef, 0x93, 0x0e, 0xbe, 0x4f, 0x3a, 0xe3, 0x74, 0xb3, + 0xb1, 0x9f, 0x86, 0x46, 0x6a, 0x01, 0x02, 0x56, 0xc0, 0xbc, 0x4b, 0x4c, 0xd2, 0x71, 0x53, 0x33, + 0x32, 0xb7, 0x99, 0xd8, 0x56, 0xd2, 0x93, 0xcd, 0x97, 0x0e, 0x0a, 0x2c, 0xfb, 0x99, 0x59, 0xe1, + 0x64, 0x20, 0xad, 0x8d, 0x99, 0x4c, 0x49, 0x14, 0x8d, 0xb1, 0xc1, 0x16, 0x80, 0x0f, 0x2c, 0xc7, + 0x6c, 0x1a, 0xc4, 0x6c, 0x36, 0xbb, 0x46, 0x1b, 0xb9, 0x9d, 0x26, 0x49, 0xcd, 0xfa, 0xf5, 0x49, + 0x67, 0x69, 0xe8, 0x5e, 0x9e, 0xe6, 0xa7, 0x65, 0x5f, 0xf3, 0x8c, 0x3d, 0x19, 0x48, 0x1b, 0x54, + 0x64, 0x92, 0x48, 0xd1, 0x78, 0x3f, 0x18, 0x02, 0xc1, 0x8f, 0x41, 0xcc, 0xed, 0x54, 0x6d, 0x8b, + 0x18, 0x5e, 0x27, 0xa7, 0xe6, 0x7c, 0x29, 0x61, 0xc2, 0x0a, 0x3d, 0x68, 0xf3, 0xac, 0xc8, 0x54, + 0x58, 0xbf, 0x84, 0xc0, 0xca, 0xa3, 0xe7, 0x12, 0xa7, 0x01, 0x1a, 0xf1, 0x00, 0xd0, 0x02, 0x3c, + 0x6b, 0x11, 0x03, 0x39, 0x75, 0xaa, 0x30, 0x7f, 0xae, 0xc2, 0xeb, 0x4c, 0x61, 0x9d, 0x2a, 0x8c, + 0x33, 0x50, 0x99, 0x04, 0x0b, 0xab, 0x4e, 0xdd, 0x97, 0x7a, 0xc8, 0x81, 0x65, 0x82, 0x89, 0xd9, + 0x34, 0xd8, 0x41, 0x6a, 0xe1, 0xbc, 0x46, 0xbc, 0xc5, 0x74, 0x92, 0x54, 0x67, 0x04, 0xad, 0x4c, + 0xd5, 0xa0, 0x71, 0x1f, 0x1b, 0x8c, 0x58, 0x13, 0x5c, 0xd8, 0xc7, 0xc4, 0x72, 0x1a, 0xde, 0xe7, + 0x6d, 0x33, 0x63, 0x17, 0xcf, 0xbd, 0xf6, 0x1b, 0xac, 0x9c, 0x14, 0x2d, 0x67, 0x82, 0x82, 0xde, + 0x7b, 0x85, 0xc6, 0xcb, 0x5e, 0xd8, 0xbf, 0xf8, 0x03, 0xc0, 0x42, 0x43, 0x8b, 0x97, 0xce, 0xd5, + 0x52, 0x98, 0xd6, 0xda, 0x88, 0xd6, 0xa8, 0xc3, 0xcb, 0x34, 0xca, 0x0c, 0xde, 0x99, 0xf5, 0xb6, + 0x8a, 0x72, 0x18, 0x05, 0xb1, 0x70, 0xfb, 0x7c, 0x00, 0x66, 0xba, 0xc8, 0xa5, 0x1b, 0x2a, 0x9b, + 0xf6, 0x58, 0x7f, 0x1b, 0x48, 0x6f, 0xfe, 0x0b, 0xe3, 0xf2, 0x0e, 0xd1, 0x3c, 0x28, 0xbc, 0x05, + 0x16, 0xcc, 0xaa, 0x4b, 0x4c, 0x8b, 0xed, 0xb2, 0xa9, 0x59, 0x02, 0x38, 0x7c, 0x1f, 0x44, 0x1d, + 0xec, 0x0f, 0xe4, 0xf4, 0x24, 0x51, 0x07, 0xc3, 0x06, 0x88, 0x3b, 0xd8, 0xf8, 0xdc, 0x22, 0x7b, + 0xc6, 0x3e, 0x22, 0xd8, 0x1f, 0xbb, 0xa5, 0xac, 0x3a, 0x1d, 0xd3, 0xc9, 0x40, 0x5a, 0xa5, 0xa6, + 0x86, 0xb9, 0x14, 0x0d, 0x38, 0xf8, 0xae, 0x45, 0xf6, 0x2a, 0x88, 0x60, 0x66, 0xe5, 0x37, 0x1c, + 0x98, 0xad, 0x60, 0x82, 0xfe, 0xfb, 0x4a, 0x4e, 0x82, 0xb9, 0x7d, 0x4c, 0x50, 0xb0, 0x8e, 0xe9, + 0x0b, 0x7c, 0x17, 0x2c, 0x60, 0xff, 0x87, 0xc0, 0xf5, 0x77, 0x71, 0x62, 0x5b, 0x3c, 0x6b, 0x71, + 0x78, 0xca, 0x45, 0x3f, 0x4d, 0x0b, 0xd2, 0x77, 0x16, 0x1f, 0x07, 0xfb, 0xf5, 0xc7, 0x28, 0x58, + 0x66, 0xed, 0x5c, 0x32, 0xdb, 0xa6, 0xed, 0xc2, 0x6f, 0x39, 0x10, 0xb3, 0x2d, 0xe7, 0x74, 0xba, + 0xb8, 0xf3, 0xa6, 0xcb, 0xf0, 0x7c, 0x3b, 0x1e, 0x48, 0x17, 0x43, 0xa8, 0x2b, 0xd8, 0xb6, 0x08, + 0xb2, 0x5b, 0xa4, 0x3b, 0xbc, 0x5d, 0xe8, 0x78, 0xba, 0xa1, 0x03, 0xb6, 0xe5, 0x04, 0x23, 0xf7, + 0x35, 0x07, 0xa0, 0x6d, 0x1e, 0x04, 0x44, 0x46, 0x0b, 0xb5, 0x2d, 0x5c, 0x67, 0x8b, 0x7d, 0x63, + 0x62, 0x10, 0x72, 0xec, 0x87, 0x97, 0x7e, 0xdc, 0xe3, 0x81, 0x74, 0x69, 0x12, 0x3c, 0x52, 0x2b, + 0x5b, 0xa9, 0x93, 0x59, 0xca, 0x63, 0x6f, 0x54, 0x78, 0xdb, 0x3c, 0x08, 0xec, 0xa2, 0xe1, 0xaf, + 0x38, 0x10, 0xaf, 0xf8, 0xf3, 0xc3, 0xfc, 0xfb, 0x02, 0xb0, 0x79, 0x0a, 0x6a, 0xe3, 0xce, 0xab, + 0xed, 0x06, 0xab, 0x6d, 0x7d, 0x04, 0x37, 0x52, 0x56, 0x72, 0x64, 0x7c, 0xc3, 0x15, 0xc5, 0x69, + 0x8c, 0x55, 0xf3, 0x7b, 0x30, 0xb5, 0xac, 0x98, 0xfb, 0x60, 0xfe, 0xb3, 0x0e, 0x6e, 0x77, 0x6c, + 0xbf, 0x8a, 0x78, 0x36, 0x3b, 0x45, 0x8f, 0xe7, 0x50, 0xed, 0x78, 0x20, 0xf1, 0x14, 0x3f, 0xac, + 0x46, 0x63, 0x8c, 0xb0, 0x06, 0x96, 0xc8, 0x5e, 0x1b, 0xb9, 0x7b, 0xb8, 0x49, 0x3f, 0x40, 0x7c, + 0xaa, 0x11, 0xa2, 0xf4, 0xab, 0xa7, 0x14, 0x21, 0x85, 0x21, 0x2f, 0xec, 0x71, 0x20, 0xe1, 0xcd, + 0x95, 0x31, 0x94, 0x9a, 0xf1, 0xa5, 0x6a, 0x53, 0x4b, 0xa5, 0x46, 0x79, 0x46, 0xfc, 0xbd, 0xc8, + 0xfc, 0x1d, 0xc9, 0x50, 0xb4, 0x65, 0x2f, 0xa0, 0x07, 0xef, 0x97, 0xff, 0xe4, 0x00, 0x18, 0x8e, + 0x13, 0xbc, 0x02, 0xd6, 0x2b, 0x45, 0x5d, 0x35, 0x8a, 0x25, 0x3d, 0x5f, 0x2c, 0x18, 0x77, 0x0a, + 0xe5, 0x92, 0xba, 0x9b, 0xbf, 0x99, 0x57, 0x73, 0x7c, 0x44, 0x58, 0xe9, 0xf5, 0xe5, 0x18, 0x4d, + 0x54, 0x3d, 0x11, 0xa8, 0x80, 0x95, 0x70, 0xf6, 0x3d, 0xb5, 0xcc, 0x73, 0xc2, 0x72, 0xaf, 0x2f, + 0x2f, 0xd1, 0xac, 0x7b, 0xc8, 0x85, 0x97, 0xc1, 0x6a, 0x38, 0x27, 0x93, 0x2d, 0xeb, 0x99, 0x7c, + 0x81, 0x8f, 0x0a, 0x17, 0x7a, 0x7d, 0x79, 0x99, 0xe6, 0x65, 0xd8, 0x12, 0x94, 0x41, 0x22, 0x9c, + 0x5b, 0x28, 0xf2, 0x33, 0x42, 0xbc, 0xd7, 0x97, 0x17, 0x69, 0x5a, 0x01, 0xc3, 0x6d, 0x90, 0x1a, + 0xcd, 0x30, 0xee, 0xe6, 0xf5, 0x5b, 0x46, 0x45, 0xd5, 0x8b, 0xfc, 0xac, 0x90, 0xec, 0xf5, 0x65, + 0x3e, 0xc8, 0x0d, 0x36, 0x96, 0x30, 0xfb, 0xf0, 0x3b, 0x31, 0x72, 0xf9, 0xe7, 0x28, 0x48, 0x8c, + 0xfe, 0xa7, 0x06, 0xa6, 0xc1, 0xff, 0x4a, 0x5a, 0xb1, 0x54, 0x2c, 0x67, 0x6e, 0x1b, 0x65, 0x3d, + 0xa3, 0xdf, 0x29, 0x8f, 0x5d, 0xd8, 0xbf, 0x0a, 0x4d, 0x2e, 0x58, 0x4d, 0x78, 0x03, 0x88, 0xe3, + 0xf9, 0x39, 0xb5, 0x54, 0x2c, 0xe7, 0x75, 0xa3, 0xa4, 0x6a, 0xf9, 0x62, 0x8e, 0xe7, 0x84, 0xf5, + 0x5e, 0x5f, 0x5e, 0xa5, 0x90, 0x91, 0xa1, 0x82, 0xef, 0x81, 0xff, 0x8f, 0x83, 0x2b, 0x45, 0x3d, + 0x5f, 0xf8, 0x30, 0xc0, 0x46, 0x85, 0xb5, 0x5e, 0x5f, 0x86, 0x14, 0x5b, 0x09, 0x4d, 0x00, 0xbc, + 0x02, 0xd6, 0xc6, 0xa1, 0xa5, 0x4c, 0xb9, 0xac, 0xe6, 0xf8, 0x19, 0x81, 0xef, 0xf5, 0xe5, 0x38, + 0xc5, 0x94, 0x4c, 0xd7, 0x45, 0x75, 0x78, 0x0d, 0xa4, 0xc6, 0xb3, 0x35, 0xf5, 0x23, 0x75, 0x57, + 0x57, 0x73, 0xfc, 0xac, 0x00, 0x7b, 0x7d, 0x39, 0x41, 0xf3, 0x35, 0xf4, 0x09, 0xaa, 0x11, 0x74, + 0x26, 0xff, 0xcd, 0x4c, 0xfe, 0xb6, 0x9a, 0xe3, 0xe7, 0xc2, 0xfc, 0x37, 0x4d, 0xab, 0x89, 0xea, + 0xd4, 0xce, 0x6c, 0xe1, 0xf0, 0x85, 0x18, 0x79, 0xf6, 0x42, 0x8c, 0x7c, 0x79, 0x24, 0x46, 0x0e, + 0x8f, 0x44, 0xee, 0xe9, 0x91, 0xc8, 0xfd, 0x71, 0x24, 0x72, 0x8f, 0x5e, 0x8a, 0x91, 0xa7, 0x2f, + 0xc5, 0xc8, 0xb3, 0x97, 0x62, 0xe4, 0xfe, 0x3f, 0x2f, 0xc4, 0x03, 0xff, 0x8f, 0x21, 0xbf, 0x9f, + 0xab, 0xf3, 0xfe, 0x0e, 0x79, 0xeb, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd9, 0xc3, 0x29, 0xda, + 0x27, 0x0d, 0x00, 0x00, } func (this *TextProposal) Equal(that interface{}) bool { @@ -937,10 +937,23 @@ func (m *Vote) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.Option != 0 { - i = encodeVarintGov(dAtA, i, uint64(m.Option)) + if len(m.Options) > 0 { + dAtA8 := make([]byte, len(m.Options)*10) + var j7 int + for _, num := range m.Options { + for num >= 1<<7 { + dAtA8[j7] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j7++ + } + dAtA8[j7] = uint8(num) + j7++ + } + i -= j7 + copy(dAtA[i:], dAtA8[:j7]) + i = encodeVarintGov(dAtA, i, uint64(j7)) i-- - dAtA[i] = 0x18 + dAtA[i] = 0x1a } if len(m.Voter) > 0 { i -= len(m.Voter) @@ -977,12 +990,12 @@ func (m *DepositParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - n7, err7 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.MaxDepositPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.MaxDepositPeriod):]) - if err7 != nil { - return 0, err7 + n9, err9 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.MaxDepositPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.MaxDepositPeriod):]) + if err9 != nil { + return 0, err9 } - i -= n7 - i = encodeVarintGov(dAtA, i, uint64(n7)) + i -= n9 + i = encodeVarintGov(dAtA, i, uint64(n9)) i-- dAtA[i] = 0x12 if len(m.MinDeposit) > 0 { @@ -1022,12 +1035,12 @@ func (m *VotingParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - n8, err8 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.VotingPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.VotingPeriod):]) - if err8 != nil { - return 0, err8 + n10, err10 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.VotingPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.VotingPeriod):]) + if err10 != nil { + return 0, err10 } - i -= n8 - i = encodeVarintGov(dAtA, i, uint64(n8)) + i -= n10 + i = encodeVarintGov(dAtA, i, uint64(n10)) i-- dAtA[i] = 0xa return len(dAtA) - i, nil @@ -1201,8 +1214,12 @@ func (m *Vote) Size() (n int) { if l > 0 { n += 1 + l + sovGov(uint64(l)) } - if m.Option != 0 { - n += 1 + sovGov(uint64(m.Option)) + if len(m.Options) > 0 { + l = 0 + for _, e := range m.Options { + l += sovGov(uint64(e)) + } + n += 1 + sovGov(uint64(l)) + l } return n } @@ -2107,23 +2124,73 @@ func (m *Vote) Unmarshal(dAtA []byte) error { m.Voter = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Option", wireType) - } - m.Option = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGov - } - if iNdEx >= l { + if wireType == 0 { + var v VoteOption + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= VoteOption(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Options = append(m.Options, v) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + packedLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { return io.ErrUnexpectedEOF } - b := dAtA[iNdEx] - iNdEx++ - m.Option |= VoteOption(b&0x7F) << shift - if b < 0x80 { - break - } + var elementCount int + if elementCount != 0 && len(m.Options) == 0 { + m.Options = make([]VoteOption, 0, elementCount) + } + for iNdEx < postIndex { + var v VoteOption + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= VoteOption(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Options = append(m.Options, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType) } default: iNdEx = preIndex From 09a282dda305cd98292173d277c7577007dc4ea9 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Tue, 27 Oct 2020 21:50:11 +1000 Subject: [PATCH 002/152] basic migration for SubVote type --- proto/cosmos/gov/v1beta1/gov.proto | 15 +- proto/cosmos/gov/v1beta1/tx.proto | 6 +- x/gov/client/rest/tx.go | 2 +- x/gov/client/utils/query.go | 4 +- x/gov/keeper/msg_server.go | 2 +- x/gov/keeper/vote.go | 4 +- x/gov/legacy/v040/migrate.go | 2 +- x/gov/types/gov.pb.go | 552 +++++++++++++++++++---------- x/gov/types/msgs.go | 10 +- x/gov/types/tx.pb.go | 130 ++++--- x/gov/types/vote.go | 26 +- 11 files changed, 486 insertions(+), 267 deletions(-) diff --git a/proto/cosmos/gov/v1beta1/gov.proto b/proto/cosmos/gov/v1beta1/gov.proto index 3c00d4b2b2f6..196545bc098b 100644 --- a/proto/cosmos/gov/v1beta1/gov.proto +++ b/proto/cosmos/gov/v1beta1/gov.proto @@ -29,6 +29,15 @@ enum VoteOption { VOTE_OPTION_NO_WITH_VETO = 4 [(gogoproto.enumvalue_customname) = "OptionNoWithVeto"]; } +message SubVote { + VoteOption option = 1; + string rate = 2 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"rate\"" + ]; +} + // TextProposal defines a standard text proposal whose changes need to be // manually updated in case of approval. message TextProposal { @@ -119,9 +128,9 @@ message Vote { option (gogoproto.goproto_stringer) = false; option (gogoproto.equal) = false; - uint64 proposal_id = 1 [(gogoproto.moretags) = "yaml:\"proposal_id\""]; - string voter = 2; - repeated VoteOption options = 3; + uint64 proposal_id = 1 [(gogoproto.moretags) = "yaml:\"proposal_id\""]; + string voter = 2; + repeated SubVote sub_votes = 3 [(gogoproto.nullable) = false]; } // DepositParams defines the params for deposits on governance proposals. diff --git a/proto/cosmos/gov/v1beta1/tx.proto b/proto/cosmos/gov/v1beta1/tx.proto index 5c0560757d24..d059874f12d7 100644 --- a/proto/cosmos/gov/v1beta1/tx.proto +++ b/proto/cosmos/gov/v1beta1/tx.proto @@ -50,9 +50,9 @@ message MsgVote { option (gogoproto.stringer) = false; option (gogoproto.goproto_getters) = false; - uint64 proposal_id = 1 [(gogoproto.jsontag) = "proposal_id", (gogoproto.moretags) = "yaml:\"proposal_id\""]; - string voter = 2; - VoteOption option = 3; + uint64 proposal_id = 1 [(gogoproto.jsontag) = "proposal_id", (gogoproto.moretags) = "yaml:\"proposal_id\""]; + string voter = 2; + repeated SubVote sub_votes = 3 [(gogoproto.nullable) = false]; } // MsgVoteResponse defines the Msg/Vote response type. diff --git a/x/gov/client/rest/tx.go b/x/gov/client/rest/tx.go index 284c67148170..4f010f27b7d3 100644 --- a/x/gov/client/rest/tx.go +++ b/x/gov/client/rest/tx.go @@ -117,7 +117,7 @@ func newVoteHandlerFn(clientCtx client.Context) http.HandlerFunc { } // create the message - msg := types.NewMsgVote(req.Voter, proposalID, voteOption) + msg := types.NewMsgVote(req.Voter, proposalID, []types.SubVote{types.NewSubVote(voteOption, 1)}) if rest.CheckBadRequestError(w, msg.ValidateBasic()) { return } diff --git a/x/gov/client/utils/query.go b/x/gov/client/utils/query.go index e543f526b3f0..44081f8ef6fb 100644 --- a/x/gov/client/utils/query.go +++ b/x/gov/client/utils/query.go @@ -101,7 +101,7 @@ func QueryVotesByTxQuery(clientCtx client.Context, params types.QueryProposalVot votes = append(votes, types.Vote{ Voter: voteMsg.Voter, ProposalId: params.ProposalID, - Option: voteMsg.Option, + SubVotes: voteMsg.SubVotes, }) } } @@ -148,7 +148,7 @@ func QueryVoteByTxQuery(clientCtx client.Context, params types.QueryVoteParams) vote := types.Vote{ Voter: voteMsg.Voter, ProposalId: params.ProposalID, - Option: voteMsg.Option, + SubVotes: voteMsg.SubVotes, } bz, err := clientCtx.JSONMarshaler.MarshalJSON(&vote) diff --git a/x/gov/keeper/msg_server.go b/x/gov/keeper/msg_server.go index aee3d3c3807a..2cedfeb23542 100644 --- a/x/gov/keeper/msg_server.go +++ b/x/gov/keeper/msg_server.go @@ -64,7 +64,7 @@ func (k msgServer) Vote(goCtx context.Context, msg *types.MsgVote) (*types.MsgVo if accErr != nil { return nil, accErr } - err := k.Keeper.AddVote(ctx, msg.ProposalId, accAddr, msg.Option) + err := k.Keeper.AddVote(ctx, msg.ProposalId, accAddr, msg.SubVotes) if err != nil { return nil, err } diff --git a/x/gov/keeper/vote.go b/x/gov/keeper/vote.go index a35569bc3465..c86a06872a30 100644 --- a/x/gov/keeper/vote.go +++ b/x/gov/keeper/vote.go @@ -9,7 +9,7 @@ import ( ) // AddVote adds a vote on a specific proposal -func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress, option types.VoteOption) error { +func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress, subvotes []types.SubVote) error { proposal, ok := keeper.GetProposal(ctx, proposalID) if !ok { return sdkerrors.Wrapf(types.ErrUnknownProposal, "%d", proposalID) @@ -22,7 +22,7 @@ func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.A return sdkerrors.Wrap(types.ErrInvalidVote, option.String()) } - vote := types.NewVote(proposalID, voterAddr, option) + vote := types.NewVote(proposalID, voterAddr, subvotes) keeper.SetVote(ctx, vote) ctx.EventManager().EmitEvent( diff --git a/x/gov/legacy/v040/migrate.go b/x/gov/legacy/v040/migrate.go index 223eb6626c70..522bbd54ca17 100644 --- a/x/gov/legacy/v040/migrate.go +++ b/x/gov/legacy/v040/migrate.go @@ -118,7 +118,7 @@ func Migrate(oldGovState v036gov.GenesisState) *v040gov.GenesisState { newVotes[i] = v040gov.Vote{ ProposalId: oldVote.ProposalID, Voter: oldVote.Voter.String(), - Option: migrateVoteOption(oldVote.Option), + SubVotes: []v040gov.SubVote{v040gov.NewSubVote(migrateVoteOption(oldVote.Option), 1)}, } } diff --git a/x/gov/types/gov.pb.go b/x/gov/types/gov.pb.go index 3028ae0c6d67..e6b65c5170c2 100644 --- a/x/gov/types/gov.pb.go +++ b/x/gov/types/gov.pb.go @@ -121,6 +121,43 @@ func (ProposalStatus) EnumDescriptor() ([]byte, []int) { return fileDescriptor_6e82113c1a9a4b7c, []int{1} } +type SubVote struct { + Option VoteOption `protobuf:"varint,1,opt,name=option,proto3,enum=cosmos.gov.v1beta1.VoteOption" json:"option,omitempty"` + Rate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=rate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"rate" yaml:"rate"` +} + +func (m *SubVote) Reset() { *m = SubVote{} } +func (*SubVote) ProtoMessage() {} +func (*SubVote) Descriptor() ([]byte, []int) { + return fileDescriptor_6e82113c1a9a4b7c, []int{0} +} +func (m *SubVote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SubVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SubVote.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 *SubVote) XXX_Merge(src proto.Message) { + xxx_messageInfo_SubVote.Merge(m, src) +} +func (m *SubVote) XXX_Size() int { + return m.Size() +} +func (m *SubVote) XXX_DiscardUnknown() { + xxx_messageInfo_SubVote.DiscardUnknown(m) +} + +var xxx_messageInfo_SubVote proto.InternalMessageInfo + // TextProposal defines a standard text proposal whose changes need to be // manually updated in case of approval. type TextProposal struct { @@ -131,7 +168,7 @@ type TextProposal struct { func (m *TextProposal) Reset() { *m = TextProposal{} } func (*TextProposal) ProtoMessage() {} func (*TextProposal) Descriptor() ([]byte, []int) { - return fileDescriptor_6e82113c1a9a4b7c, []int{0} + return fileDescriptor_6e82113c1a9a4b7c, []int{1} } func (m *TextProposal) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -171,7 +208,7 @@ type Deposit struct { func (m *Deposit) Reset() { *m = Deposit{} } func (*Deposit) ProtoMessage() {} func (*Deposit) Descriptor() ([]byte, []int) { - return fileDescriptor_6e82113c1a9a4b7c, []int{1} + return fileDescriptor_6e82113c1a9a4b7c, []int{2} } func (m *Deposit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -216,7 +253,7 @@ type Proposal struct { func (m *Proposal) Reset() { *m = Proposal{} } func (*Proposal) ProtoMessage() {} func (*Proposal) Descriptor() ([]byte, []int) { - return fileDescriptor_6e82113c1a9a4b7c, []int{2} + return fileDescriptor_6e82113c1a9a4b7c, []int{3} } func (m *Proposal) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -256,7 +293,7 @@ type TallyResult struct { func (m *TallyResult) Reset() { *m = TallyResult{} } func (*TallyResult) ProtoMessage() {} func (*TallyResult) Descriptor() ([]byte, []int) { - return fileDescriptor_6e82113c1a9a4b7c, []int{3} + return fileDescriptor_6e82113c1a9a4b7c, []int{4} } func (m *TallyResult) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -288,15 +325,15 @@ var xxx_messageInfo_TallyResult proto.InternalMessageInfo // Vote defines a vote on a governance proposal. // A Vote consists of a proposal ID, the voter, and the vote option. type Vote struct { - ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty" yaml:"proposal_id"` - Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` - Options []VoteOption `protobuf:"varint,3,rep,packed,name=options,proto3,enum=cosmos.gov.v1beta1.VoteOption" json:"options,omitempty"` + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty" yaml:"proposal_id"` + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` + SubVotes []SubVote `protobuf:"bytes,3,rep,name=sub_votes,json=subVotes,proto3" json:"sub_votes"` } func (m *Vote) Reset() { *m = Vote{} } func (*Vote) ProtoMessage() {} func (*Vote) Descriptor() ([]byte, []int) { - return fileDescriptor_6e82113c1a9a4b7c, []int{4} + return fileDescriptor_6e82113c1a9a4b7c, []int{5} } func (m *Vote) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -337,7 +374,7 @@ type DepositParams struct { func (m *DepositParams) Reset() { *m = DepositParams{} } func (*DepositParams) ProtoMessage() {} func (*DepositParams) Descriptor() ([]byte, []int) { - return fileDescriptor_6e82113c1a9a4b7c, []int{5} + return fileDescriptor_6e82113c1a9a4b7c, []int{6} } func (m *DepositParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -375,7 +412,7 @@ type VotingParams struct { func (m *VotingParams) Reset() { *m = VotingParams{} } func (*VotingParams) ProtoMessage() {} func (*VotingParams) Descriptor() ([]byte, []int) { - return fileDescriptor_6e82113c1a9a4b7c, []int{6} + return fileDescriptor_6e82113c1a9a4b7c, []int{7} } func (m *VotingParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -419,7 +456,7 @@ type TallyParams struct { func (m *TallyParams) Reset() { *m = TallyParams{} } func (*TallyParams) ProtoMessage() {} func (*TallyParams) Descriptor() ([]byte, []int) { - return fileDescriptor_6e82113c1a9a4b7c, []int{7} + return fileDescriptor_6e82113c1a9a4b7c, []int{8} } func (m *TallyParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -451,6 +488,7 @@ var xxx_messageInfo_TallyParams proto.InternalMessageInfo func init() { proto.RegisterEnum("cosmos.gov.v1beta1.VoteOption", VoteOption_name, VoteOption_value) proto.RegisterEnum("cosmos.gov.v1beta1.ProposalStatus", ProposalStatus_name, ProposalStatus_value) + proto.RegisterType((*SubVote)(nil), "cosmos.gov.v1beta1.SubVote") proto.RegisterType((*TextProposal)(nil), "cosmos.gov.v1beta1.TextProposal") proto.RegisterType((*Deposit)(nil), "cosmos.gov.v1beta1.Deposit") proto.RegisterType((*Proposal)(nil), "cosmos.gov.v1beta1.Proposal") @@ -464,94 +502,98 @@ func init() { func init() { proto.RegisterFile("cosmos/gov/v1beta1/gov.proto", fileDescriptor_6e82113c1a9a4b7c) } var fileDescriptor_6e82113c1a9a4b7c = []byte{ - // 1380 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0x5f, 0x6c, 0xdb, 0xd4, - 0x17, 0x8e, 0xd3, 0xff, 0x37, 0x69, 0xea, 0xdd, 0x66, 0x6d, 0xea, 0xdf, 0x7e, 0xb6, 0x31, 0x08, - 0x55, 0xd3, 0x96, 0x6e, 0x05, 0x09, 0xe8, 0x24, 0x44, 0xd2, 0x78, 0x2c, 0x68, 0x4a, 0x22, 0xc7, - 0xcb, 0xb4, 0xf1, 0x60, 0x39, 0xc9, 0x5d, 0x6a, 0x88, 0x7d, 0x43, 0x7c, 0x53, 0x1a, 0xf1, 0xc2, - 0xe3, 0x14, 0x24, 0xb4, 0xc7, 0x21, 0x14, 0x69, 0x12, 0x6f, 0x3c, 0xf3, 0xcc, 0x73, 0x85, 0x90, - 0x98, 0x78, 0x9a, 0x40, 0xca, 0x58, 0x27, 0xa1, 0xa9, 0x8f, 0x7d, 0xe0, 0x19, 0xd9, 0xf7, 0xba, - 0x71, 0x92, 0x8a, 0x12, 0x9e, 0x66, 0x9f, 0x7b, 0xbe, 0xef, 0x3b, 0xf7, 0xf3, 0x39, 0x27, 0x2b, - 0xb8, 0x54, 0xc3, 0xae, 0x8d, 0xdd, 0xad, 0x06, 0xde, 0xdf, 0xda, 0xbf, 0x5e, 0x45, 0xc4, 0xbc, - 0xee, 0x3d, 0xa7, 0x5b, 0x6d, 0x4c, 0x30, 0x84, 0xf4, 0x34, 0xed, 0x45, 0xd8, 0xa9, 0x20, 0x32, - 0x44, 0xd5, 0x74, 0xd1, 0x29, 0xa4, 0x86, 0x2d, 0x87, 0x62, 0x84, 0x64, 0x03, 0x37, 0xb0, 0xff, - 0xb8, 0xe5, 0x3d, 0xb1, 0xe8, 0x06, 0x45, 0x19, 0xf4, 0x80, 0xd1, 0xd2, 0x23, 0xa9, 0x81, 0x71, - 0xa3, 0x89, 0xb6, 0xfc, 0xb7, 0x6a, 0xe7, 0xc1, 0x16, 0xb1, 0x6c, 0xe4, 0x12, 0xd3, 0x6e, 0x05, - 0xd8, 0xf1, 0x04, 0xd3, 0xe9, 0xb2, 0x23, 0x71, 0xfc, 0xa8, 0xde, 0x69, 0x9b, 0xc4, 0xc2, 0xac, - 0x18, 0xe5, 0x2e, 0x88, 0xeb, 0xe8, 0x80, 0x94, 0xda, 0xb8, 0x85, 0x5d, 0xb3, 0x09, 0x93, 0x60, - 0x8e, 0x58, 0xa4, 0x89, 0x52, 0x9c, 0xcc, 0x6d, 0x2e, 0x69, 0xf4, 0x05, 0xca, 0x20, 0x56, 0x47, - 0x6e, 0xad, 0x6d, 0xb5, 0x3c, 0x68, 0x2a, 0xea, 0x9f, 0x85, 0x43, 0x3b, 0x2b, 0xaf, 0x9e, 0x48, - 0xdc, 0xaf, 0x3f, 0x5c, 0x5d, 0xd8, 0xc5, 0x0e, 0x41, 0x0e, 0x51, 0x7e, 0xe1, 0xc0, 0x42, 0x0e, - 0xb5, 0xb0, 0x6b, 0x11, 0xf8, 0x0e, 0x88, 0xb5, 0x98, 0x80, 0x61, 0xd5, 0x7d, 0xea, 0xd9, 0xec, - 0xda, 0xc9, 0x40, 0x82, 0x5d, 0xd3, 0x6e, 0xee, 0x28, 0xa1, 0x43, 0x45, 0x03, 0xc1, 0x5b, 0xbe, - 0x0e, 0x2f, 0x81, 0xa5, 0x3a, 0xe5, 0xc0, 0x6d, 0xa6, 0x3a, 0x0c, 0xc0, 0x1a, 0x98, 0x37, 0x6d, - 0xdc, 0x71, 0x48, 0x6a, 0x46, 0x9e, 0xd9, 0x8c, 0x6d, 0x6f, 0xa4, 0x99, 0x6d, 0x9e, 0xf3, 0xc1, - 0xe7, 0x48, 0xef, 0x62, 0xcb, 0xc9, 0x5e, 0x3b, 0x1c, 0x48, 0x91, 0xef, 0x9f, 0x4b, 0x9b, 0x0d, - 0x8b, 0xec, 0x75, 0xaa, 0xe9, 0x1a, 0xb6, 0x99, 0xc7, 0xec, 0x9f, 0xab, 0x6e, 0xfd, 0xd3, 0x2d, - 0xd2, 0x6d, 0x21, 0xd7, 0x07, 0xb8, 0x1a, 0xa3, 0xde, 0x59, 0x7c, 0xf8, 0x44, 0x8a, 0xbc, 0x7a, - 0x22, 0x45, 0x94, 0xbf, 0xe6, 0xc1, 0xe2, 0xa9, 0x4f, 0x6f, 0x9f, 0x75, 0xa5, 0xd5, 0xe3, 0x81, - 0x14, 0xb5, 0xea, 0x27, 0x03, 0x69, 0x89, 0x5e, 0x6c, 0xfc, 0x3e, 0x37, 0xc0, 0x42, 0x8d, 0xfa, - 0xe3, 0xdf, 0x26, 0xb6, 0x9d, 0x4c, 0xd3, 0xef, 0x93, 0x0e, 0xbe, 0x4f, 0x3a, 0xe3, 0x74, 0xb3, - 0xb1, 0x9f, 0x86, 0x46, 0x6a, 0x01, 0x02, 0x56, 0xc0, 0xbc, 0x4b, 0x4c, 0xd2, 0x71, 0x53, 0x33, - 0x32, 0xb7, 0x99, 0xd8, 0x56, 0xd2, 0x93, 0xcd, 0x97, 0x0e, 0x0a, 0x2c, 0xfb, 0x99, 0x59, 0xe1, - 0x64, 0x20, 0xad, 0x8d, 0x99, 0x4c, 0x49, 0x14, 0x8d, 0xb1, 0xc1, 0x16, 0x80, 0x0f, 0x2c, 0xc7, - 0x6c, 0x1a, 0xc4, 0x6c, 0x36, 0xbb, 0x46, 0x1b, 0xb9, 0x9d, 0x26, 0x49, 0xcd, 0xfa, 0xf5, 0x49, - 0x67, 0x69, 0xe8, 0x5e, 0x9e, 0xe6, 0xa7, 0x65, 0x5f, 0xf3, 0x8c, 0x3d, 0x19, 0x48, 0x1b, 0x54, - 0x64, 0x92, 0x48, 0xd1, 0x78, 0x3f, 0x18, 0x02, 0xc1, 0x8f, 0x41, 0xcc, 0xed, 0x54, 0x6d, 0x8b, - 0x18, 0x5e, 0x27, 0xa7, 0xe6, 0x7c, 0x29, 0x61, 0xc2, 0x0a, 0x3d, 0x68, 0xf3, 0xac, 0xc8, 0x54, - 0x58, 0xbf, 0x84, 0xc0, 0xca, 0xa3, 0xe7, 0x12, 0xa7, 0x01, 0x1a, 0xf1, 0x00, 0xd0, 0x02, 0x3c, - 0x6b, 0x11, 0x03, 0x39, 0x75, 0xaa, 0x30, 0x7f, 0xae, 0xc2, 0xeb, 0x4c, 0x61, 0x9d, 0x2a, 0x8c, - 0x33, 0x50, 0x99, 0x04, 0x0b, 0xab, 0x4e, 0xdd, 0x97, 0x7a, 0xc8, 0x81, 0x65, 0x82, 0x89, 0xd9, - 0x34, 0xd8, 0x41, 0x6a, 0xe1, 0xbc, 0x46, 0xbc, 0xc5, 0x74, 0x92, 0x54, 0x67, 0x04, 0xad, 0x4c, - 0xd5, 0xa0, 0x71, 0x1f, 0x1b, 0x8c, 0x58, 0x13, 0x5c, 0xd8, 0xc7, 0xc4, 0x72, 0x1a, 0xde, 0xe7, - 0x6d, 0x33, 0x63, 0x17, 0xcf, 0xbd, 0xf6, 0x1b, 0xac, 0x9c, 0x14, 0x2d, 0x67, 0x82, 0x82, 0xde, - 0x7b, 0x85, 0xc6, 0xcb, 0x5e, 0xd8, 0xbf, 0xf8, 0x03, 0xc0, 0x42, 0x43, 0x8b, 0x97, 0xce, 0xd5, - 0x52, 0x98, 0xd6, 0xda, 0x88, 0xd6, 0xa8, 0xc3, 0xcb, 0x34, 0xca, 0x0c, 0xde, 0x99, 0xf5, 0xb6, - 0x8a, 0x72, 0x18, 0x05, 0xb1, 0x70, 0xfb, 0x7c, 0x00, 0x66, 0xba, 0xc8, 0xa5, 0x1b, 0x2a, 0x9b, - 0xf6, 0x58, 0x7f, 0x1b, 0x48, 0x6f, 0xfe, 0x0b, 0xe3, 0xf2, 0x0e, 0xd1, 0x3c, 0x28, 0xbc, 0x05, - 0x16, 0xcc, 0xaa, 0x4b, 0x4c, 0x8b, 0xed, 0xb2, 0xa9, 0x59, 0x02, 0x38, 0x7c, 0x1f, 0x44, 0x1d, - 0xec, 0x0f, 0xe4, 0xf4, 0x24, 0x51, 0x07, 0xc3, 0x06, 0x88, 0x3b, 0xd8, 0xf8, 0xdc, 0x22, 0x7b, - 0xc6, 0x3e, 0x22, 0xd8, 0x1f, 0xbb, 0xa5, 0xac, 0x3a, 0x1d, 0xd3, 0xc9, 0x40, 0x5a, 0xa5, 0xa6, - 0x86, 0xb9, 0x14, 0x0d, 0x38, 0xf8, 0xae, 0x45, 0xf6, 0x2a, 0x88, 0x60, 0x66, 0xe5, 0x37, 0x1c, - 0x98, 0xad, 0x60, 0x82, 0xfe, 0xfb, 0x4a, 0x4e, 0x82, 0xb9, 0x7d, 0x4c, 0x50, 0xb0, 0x8e, 0xe9, - 0x0b, 0x7c, 0x17, 0x2c, 0x60, 0xff, 0x87, 0xc0, 0xf5, 0x77, 0x71, 0x62, 0x5b, 0x3c, 0x6b, 0x71, - 0x78, 0xca, 0x45, 0x3f, 0x4d, 0x0b, 0xd2, 0x77, 0x16, 0x1f, 0x07, 0xfb, 0xf5, 0xc7, 0x28, 0x58, - 0x66, 0xed, 0x5c, 0x32, 0xdb, 0xa6, 0xed, 0xc2, 0x6f, 0x39, 0x10, 0xb3, 0x2d, 0xe7, 0x74, 0xba, - 0xb8, 0xf3, 0xa6, 0xcb, 0xf0, 0x7c, 0x3b, 0x1e, 0x48, 0x17, 0x43, 0xa8, 0x2b, 0xd8, 0xb6, 0x08, - 0xb2, 0x5b, 0xa4, 0x3b, 0xbc, 0x5d, 0xe8, 0x78, 0xba, 0xa1, 0x03, 0xb6, 0xe5, 0x04, 0x23, 0xf7, - 0x35, 0x07, 0xa0, 0x6d, 0x1e, 0x04, 0x44, 0x46, 0x0b, 0xb5, 0x2d, 0x5c, 0x67, 0x8b, 0x7d, 0x63, - 0x62, 0x10, 0x72, 0xec, 0x87, 0x97, 0x7e, 0xdc, 0xe3, 0x81, 0x74, 0x69, 0x12, 0x3c, 0x52, 0x2b, - 0x5b, 0xa9, 0x93, 0x59, 0xca, 0x63, 0x6f, 0x54, 0x78, 0xdb, 0x3c, 0x08, 0xec, 0xa2, 0xe1, 0xaf, - 0x38, 0x10, 0xaf, 0xf8, 0xf3, 0xc3, 0xfc, 0xfb, 0x02, 0xb0, 0x79, 0x0a, 0x6a, 0xe3, 0xce, 0xab, - 0xed, 0x06, 0xab, 0x6d, 0x7d, 0x04, 0x37, 0x52, 0x56, 0x72, 0x64, 0x7c, 0xc3, 0x15, 0xc5, 0x69, - 0x8c, 0x55, 0xf3, 0x7b, 0x30, 0xb5, 0xac, 0x98, 0xfb, 0x60, 0xfe, 0xb3, 0x0e, 0x6e, 0x77, 0x6c, - 0xbf, 0x8a, 0x78, 0x36, 0x3b, 0x45, 0x8f, 0xe7, 0x50, 0xed, 0x78, 0x20, 0xf1, 0x14, 0x3f, 0xac, - 0x46, 0x63, 0x8c, 0xb0, 0x06, 0x96, 0xc8, 0x5e, 0x1b, 0xb9, 0x7b, 0xb8, 0x49, 0x3f, 0x40, 0x7c, - 0xaa, 0x11, 0xa2, 0xf4, 0xab, 0xa7, 0x14, 0x21, 0x85, 0x21, 0x2f, 0xec, 0x71, 0x20, 0xe1, 0xcd, - 0x95, 0x31, 0x94, 0x9a, 0xf1, 0xa5, 0x6a, 0x53, 0x4b, 0xa5, 0x46, 0x79, 0x46, 0xfc, 0xbd, 0xc8, - 0xfc, 0x1d, 0xc9, 0x50, 0xb4, 0x65, 0x2f, 0xa0, 0x07, 0xef, 0x97, 0xff, 0xe4, 0x00, 0x18, 0x8e, - 0x13, 0xbc, 0x02, 0xd6, 0x2b, 0x45, 0x5d, 0x35, 0x8a, 0x25, 0x3d, 0x5f, 0x2c, 0x18, 0x77, 0x0a, - 0xe5, 0x92, 0xba, 0x9b, 0xbf, 0x99, 0x57, 0x73, 0x7c, 0x44, 0x58, 0xe9, 0xf5, 0xe5, 0x18, 0x4d, - 0x54, 0x3d, 0x11, 0xa8, 0x80, 0x95, 0x70, 0xf6, 0x3d, 0xb5, 0xcc, 0x73, 0xc2, 0x72, 0xaf, 0x2f, - 0x2f, 0xd1, 0xac, 0x7b, 0xc8, 0x85, 0x97, 0xc1, 0x6a, 0x38, 0x27, 0x93, 0x2d, 0xeb, 0x99, 0x7c, - 0x81, 0x8f, 0x0a, 0x17, 0x7a, 0x7d, 0x79, 0x99, 0xe6, 0x65, 0xd8, 0x12, 0x94, 0x41, 0x22, 0x9c, - 0x5b, 0x28, 0xf2, 0x33, 0x42, 0xbc, 0xd7, 0x97, 0x17, 0x69, 0x5a, 0x01, 0xc3, 0x6d, 0x90, 0x1a, - 0xcd, 0x30, 0xee, 0xe6, 0xf5, 0x5b, 0x46, 0x45, 0xd5, 0x8b, 0xfc, 0xac, 0x90, 0xec, 0xf5, 0x65, - 0x3e, 0xc8, 0x0d, 0x36, 0x96, 0x30, 0xfb, 0xf0, 0x3b, 0x31, 0x72, 0xf9, 0xe7, 0x28, 0x48, 0x8c, - 0xfe, 0xa7, 0x06, 0xa6, 0xc1, 0xff, 0x4a, 0x5a, 0xb1, 0x54, 0x2c, 0x67, 0x6e, 0x1b, 0x65, 0x3d, - 0xa3, 0xdf, 0x29, 0x8f, 0x5d, 0xd8, 0xbf, 0x0a, 0x4d, 0x2e, 0x58, 0x4d, 0x78, 0x03, 0x88, 0xe3, - 0xf9, 0x39, 0xb5, 0x54, 0x2c, 0xe7, 0x75, 0xa3, 0xa4, 0x6a, 0xf9, 0x62, 0x8e, 0xe7, 0x84, 0xf5, - 0x5e, 0x5f, 0x5e, 0xa5, 0x90, 0x91, 0xa1, 0x82, 0xef, 0x81, 0xff, 0x8f, 0x83, 0x2b, 0x45, 0x3d, - 0x5f, 0xf8, 0x30, 0xc0, 0x46, 0x85, 0xb5, 0x5e, 0x5f, 0x86, 0x14, 0x5b, 0x09, 0x4d, 0x00, 0xbc, - 0x02, 0xd6, 0xc6, 0xa1, 0xa5, 0x4c, 0xb9, 0xac, 0xe6, 0xf8, 0x19, 0x81, 0xef, 0xf5, 0xe5, 0x38, - 0xc5, 0x94, 0x4c, 0xd7, 0x45, 0x75, 0x78, 0x0d, 0xa4, 0xc6, 0xb3, 0x35, 0xf5, 0x23, 0x75, 0x57, - 0x57, 0x73, 0xfc, 0xac, 0x00, 0x7b, 0x7d, 0x39, 0x41, 0xf3, 0x35, 0xf4, 0x09, 0xaa, 0x11, 0x74, - 0x26, 0xff, 0xcd, 0x4c, 0xfe, 0xb6, 0x9a, 0xe3, 0xe7, 0xc2, 0xfc, 0x37, 0x4d, 0xab, 0x89, 0xea, - 0xd4, 0xce, 0x6c, 0xe1, 0xf0, 0x85, 0x18, 0x79, 0xf6, 0x42, 0x8c, 0x7c, 0x79, 0x24, 0x46, 0x0e, - 0x8f, 0x44, 0xee, 0xe9, 0x91, 0xc8, 0xfd, 0x71, 0x24, 0x72, 0x8f, 0x5e, 0x8a, 0x91, 0xa7, 0x2f, - 0xc5, 0xc8, 0xb3, 0x97, 0x62, 0xe4, 0xfe, 0x3f, 0x2f, 0xc4, 0x03, 0xff, 0x8f, 0x21, 0xbf, 0x9f, - 0xab, 0xf3, 0xfe, 0x0e, 0x79, 0xeb, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd9, 0xc3, 0x29, 0xda, - 0x27, 0x0d, 0x00, 0x00, + // 1442 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0x5f, 0x6c, 0xdb, 0x54, + 0x17, 0x8f, 0xd3, 0xf4, 0x4f, 0x6e, 0xd2, 0xd6, 0xbb, 0xed, 0xda, 0x34, 0xdb, 0x67, 0xfb, 0xf3, + 0xf7, 0x09, 0x55, 0xd3, 0x96, 0x6e, 0x05, 0x81, 0xe8, 0xc4, 0x44, 0xdc, 0x78, 0x2c, 0x68, 0x4a, + 0x82, 0xe3, 0x65, 0xda, 0x78, 0xb0, 0x9c, 0xe4, 0x2e, 0x35, 0xc4, 0xbe, 0x21, 0xbe, 0x29, 0xad, + 0x78, 0xe1, 0x71, 0x0a, 0x12, 0xda, 0x03, 0x0f, 0x93, 0x50, 0xc4, 0x24, 0xde, 0x78, 0xe6, 0x99, + 0xe7, 0x0a, 0x21, 0x31, 0xf1, 0x34, 0x81, 0x94, 0xb1, 0x4e, 0x42, 0x53, 0x1f, 0xfb, 0xc0, 0x33, + 0xb2, 0xef, 0x75, 0xe3, 0x24, 0x15, 0x25, 0x3c, 0xd5, 0xf7, 0xdc, 0xf3, 0xfb, 0xfd, 0xce, 0x39, + 0x3e, 0xe7, 0xc4, 0x05, 0x17, 0x6b, 0xd8, 0xb5, 0xb1, 0xbb, 0xd1, 0xc0, 0xbb, 0x1b, 0xbb, 0xd7, + 0xaa, 0x88, 0x98, 0xd7, 0xbc, 0xe7, 0x4c, 0xab, 0x8d, 0x09, 0x86, 0x90, 0xde, 0x66, 0x3c, 0x0b, + 0xbb, 0x4d, 0x0b, 0x0c, 0x51, 0x35, 0x5d, 0x74, 0x02, 0xa9, 0x61, 0xcb, 0xa1, 0x98, 0xf4, 0x72, + 0x03, 0x37, 0xb0, 0xff, 0xb8, 0xe1, 0x3d, 0x31, 0xeb, 0x1a, 0x45, 0x19, 0xf4, 0x82, 0xd1, 0xd2, + 0x2b, 0xb1, 0x81, 0x71, 0xa3, 0x89, 0x36, 0xfc, 0x53, 0xb5, 0xf3, 0x60, 0x83, 0x58, 0x36, 0x72, + 0x89, 0x69, 0xb7, 0x02, 0xec, 0xa8, 0x83, 0xe9, 0xec, 0xb3, 0x2b, 0x61, 0xf4, 0xaa, 0xde, 0x69, + 0x9b, 0xc4, 0xc2, 0x2c, 0x18, 0xf9, 0x2b, 0x0e, 0xcc, 0x96, 0x3b, 0xd5, 0x0a, 0x26, 0x08, 0xbe, + 0x09, 0x66, 0x70, 0xcb, 0xbb, 0x4b, 0x71, 0x12, 0xb7, 0xbe, 0xb0, 0x29, 0x64, 0xc6, 0xb3, 0xcb, + 0x78, 0x9e, 0x45, 0xdf, 0x4b, 0x63, 0xde, 0xf0, 0x03, 0x10, 0x6b, 0x9b, 0x04, 0xa5, 0xa2, 0x12, + 0xb7, 0x1e, 0x57, 0xde, 0x39, 0xe8, 0x8b, 0x91, 0x5f, 0xfb, 0xe2, 0x6b, 0x0d, 0x8b, 0xec, 0x74, + 0xaa, 0x99, 0x1a, 0xb6, 0x59, 0x3a, 0xec, 0xcf, 0x15, 0xb7, 0xfe, 0xf1, 0x06, 0xd9, 0x6f, 0x21, + 0x37, 0x93, 0x43, 0xb5, 0xe3, 0xbe, 0x98, 0xd8, 0x37, 0xed, 0xe6, 0x96, 0xec, 0x71, 0xc8, 0x9a, + 0x4f, 0x25, 0xdf, 0x05, 0x49, 0x1d, 0xed, 0x91, 0x52, 0x1b, 0xb7, 0xb0, 0x6b, 0x36, 0xe1, 0x32, + 0x98, 0x26, 0x16, 0x69, 0x22, 0x3f, 0xb2, 0xb8, 0x46, 0x0f, 0x50, 0x02, 0x89, 0x3a, 0x72, 0x6b, + 0x6d, 0x8b, 0x46, 0xed, 0xeb, 0x6b, 0x61, 0xd3, 0xd6, 0xe2, 0xab, 0x27, 0x22, 0xf7, 0xcb, 0xf7, + 0x57, 0x66, 0xb7, 0xb1, 0x43, 0x90, 0x43, 0xe4, 0x9f, 0x39, 0x30, 0x9b, 0x43, 0x2d, 0xec, 0x5a, + 0x04, 0xbe, 0x05, 0x12, 0x2d, 0x26, 0x60, 0x58, 0x75, 0x9f, 0x3a, 0xa6, 0xac, 0x1c, 0xf7, 0x45, + 0x48, 0x03, 0x0a, 0x5d, 0xca, 0x1a, 0x08, 0x4e, 0xf9, 0x3a, 0xbc, 0x08, 0xe2, 0x75, 0xca, 0x81, + 0xdb, 0x4c, 0x75, 0x60, 0x80, 0x35, 0x30, 0x63, 0xda, 0xb8, 0xe3, 0x90, 0xd4, 0x94, 0x34, 0xb5, + 0x9e, 0xd8, 0x5c, 0x0b, 0xca, 0xe8, 0x35, 0xc4, 0x49, 0x1d, 0xb7, 0xb1, 0xe5, 0x28, 0x57, 0xbd, + 0x5a, 0x7d, 0xf7, 0x5c, 0x5c, 0xff, 0x07, 0xb5, 0xf2, 0x00, 0xae, 0xc6, 0xa8, 0xb7, 0xe6, 0x1e, + 0x3e, 0x11, 0x23, 0xaf, 0x9e, 0x88, 0x11, 0xf9, 0xcf, 0x19, 0x30, 0x77, 0x52, 0xa7, 0x37, 0x4e, + 0x4b, 0x69, 0xe9, 0xa8, 0x2f, 0x46, 0xad, 0xfa, 0x71, 0x5f, 0x8c, 0xd3, 0xc4, 0x46, 0xf3, 0xb9, + 0x0e, 0x66, 0x6b, 0xb4, 0x3e, 0x7e, 0x36, 0x89, 0xcd, 0xe5, 0x0c, 0x6d, 0x9b, 0x4c, 0xd0, 0x36, + 0x99, 0xac, 0xb3, 0xaf, 0x24, 0x7e, 0x1c, 0x14, 0x52, 0x0b, 0x10, 0xb0, 0x02, 0x66, 0x5c, 0x62, + 0x92, 0x8e, 0x9b, 0x9a, 0xf2, 0xbb, 0x46, 0x3e, 0xad, 0x6b, 0x82, 0x00, 0xcb, 0xbe, 0xa7, 0x92, + 0x3e, 0xee, 0x8b, 0x2b, 0x23, 0x45, 0xa6, 0x24, 0xb2, 0xc6, 0xd8, 0x60, 0x0b, 0xc0, 0x07, 0x96, + 0x63, 0x36, 0x0d, 0x62, 0x36, 0x9b, 0xfb, 0x46, 0x1b, 0xb9, 0x9d, 0x26, 0x49, 0xc5, 0xfc, 0xf8, + 0xc4, 0xd3, 0x34, 0x74, 0xcf, 0x4f, 0xf3, 0xdd, 0x94, 0xff, 0x7a, 0x85, 0x3d, 0xee, 0x8b, 0x6b, + 0x54, 0x64, 0x9c, 0x48, 0xd6, 0x78, 0xdf, 0x18, 0x02, 0xc1, 0x0f, 0x41, 0xc2, 0xed, 0x54, 0x6d, + 0x8b, 0x18, 0xde, 0x80, 0xa5, 0xa6, 0x7d, 0xa9, 0xf4, 0x58, 0x29, 0xf4, 0x60, 0xfa, 0x14, 0x81, + 0xa9, 0xb0, 0x7e, 0x09, 0x81, 0xe5, 0x47, 0xcf, 0x45, 0x4e, 0x03, 0xd4, 0xe2, 0x01, 0xa0, 0x05, + 0x78, 0xd6, 0x22, 0x06, 0x72, 0xea, 0x54, 0x61, 0xe6, 0x4c, 0x85, 0xff, 0x31, 0x85, 0x55, 0xaa, + 0x30, 0xca, 0x40, 0x65, 0x16, 0x98, 0x59, 0x75, 0xea, 0xbe, 0xd4, 0x43, 0x0e, 0xcc, 0x13, 0x4c, + 0xcc, 0xa6, 0xc1, 0x2e, 0x52, 0xb3, 0x67, 0x35, 0xe2, 0x2d, 0xa6, 0xb3, 0x4c, 0x75, 0x86, 0xd0, + 0xf2, 0x44, 0x0d, 0x9a, 0xf4, 0xb1, 0xc1, 0x88, 0x35, 0xc1, 0xb9, 0x5d, 0x4c, 0x2c, 0xa7, 0xe1, + 0xbd, 0xde, 0x36, 0x2b, 0xec, 0xdc, 0x99, 0x69, 0xff, 0x9f, 0x85, 0x93, 0xa2, 0xe1, 0x8c, 0x51, + 0xd0, 0xbc, 0x17, 0xa9, 0xbd, 0xec, 0x99, 0xfd, 0xc4, 0x1f, 0x00, 0x66, 0x1a, 0x94, 0x38, 0x7e, + 0xa6, 0x96, 0xcc, 0xb4, 0x56, 0x86, 0xb4, 0x86, 0x2b, 0x3c, 0x4f, 0xad, 0xac, 0xc0, 0x5b, 0x31, + 0x6f, 0xab, 0xc8, 0x07, 0x51, 0x90, 0x08, 0xb7, 0xcf, 0xbb, 0x60, 0x6a, 0x1f, 0xb9, 0x74, 0x43, + 0x29, 0x99, 0x09, 0xb6, 0x60, 0xde, 0x21, 0x9a, 0x07, 0x85, 0xb7, 0xc0, 0xac, 0x59, 0x75, 0x89, + 0x69, 0xb1, 0x5d, 0x36, 0x31, 0x4b, 0x00, 0x87, 0x37, 0x40, 0xd4, 0xc1, 0xfe, 0x40, 0x4e, 0x4e, + 0x12, 0x75, 0x30, 0x6c, 0x80, 0xa4, 0x83, 0x8d, 0x4f, 0x2d, 0xb2, 0x63, 0xec, 0x22, 0x82, 0xfd, + 0xb1, 0x8b, 0x2b, 0xea, 0x64, 0x4c, 0xc7, 0x7d, 0x71, 0x89, 0x16, 0x35, 0xcc, 0x25, 0x6b, 0xc0, + 0xc1, 0x77, 0x2d, 0xb2, 0x53, 0x41, 0x04, 0xb3, 0x52, 0x7e, 0xc3, 0x81, 0x98, 0xff, 0x13, 0xf4, + 0xaf, 0x57, 0xf2, 0x32, 0x98, 0xde, 0xc5, 0x04, 0x05, 0xeb, 0x98, 0x1e, 0xe0, 0x0d, 0x10, 0x77, + 0x3b, 0x55, 0xc3, 0x3b, 0xb8, 0x6c, 0x1b, 0x5f, 0x38, 0x6d, 0x75, 0xb0, 0x5f, 0x40, 0x25, 0xe6, + 0x25, 0xa8, 0xcd, 0xb9, 0xf4, 0xe8, 0x6e, 0xcd, 0x3d, 0x0e, 0xb6, 0xec, 0x0f, 0x51, 0x30, 0xcf, + 0x9a, 0xba, 0x64, 0xb6, 0x4d, 0xdb, 0x85, 0x5f, 0x73, 0x20, 0x61, 0x5b, 0xce, 0xc9, 0x8c, 0x71, + 0x67, 0xcd, 0x98, 0xe1, 0x91, 0x1f, 0xf5, 0xc5, 0xf3, 0x21, 0xd4, 0x65, 0x6c, 0x5b, 0x04, 0xd9, + 0x2d, 0xb2, 0x3f, 0xc8, 0x31, 0x74, 0x3d, 0xd9, 0xe8, 0x01, 0xdb, 0x72, 0x82, 0xc1, 0xfb, 0x92, + 0x03, 0xd0, 0x36, 0xf7, 0x02, 0x22, 0xa3, 0x85, 0xda, 0x16, 0xae, 0xb3, 0xf5, 0xbe, 0x36, 0x36, + 0x0e, 0x39, 0xf6, 0x55, 0x40, 0x5f, 0xf1, 0x51, 0x5f, 0xbc, 0x38, 0x0e, 0x1e, 0x8a, 0x95, 0x2d, + 0xd6, 0x71, 0x2f, 0xf9, 0xb1, 0x37, 0x30, 0xbc, 0x6d, 0xee, 0x05, 0xe5, 0xa2, 0xe6, 0x2f, 0x38, + 0x90, 0xac, 0xf8, 0x53, 0xc4, 0xea, 0xf7, 0x19, 0x60, 0x53, 0x15, 0xc4, 0xc6, 0x9d, 0x15, 0xdb, + 0x75, 0x16, 0xdb, 0xea, 0x10, 0x6e, 0x28, 0xac, 0xe5, 0xa1, 0x21, 0x0e, 0x47, 0x94, 0xa4, 0x36, + 0x16, 0xcd, 0x6f, 0xc1, 0xec, 0xb2, 0x60, 0xee, 0x83, 0x99, 0x4f, 0x3a, 0xb8, 0xdd, 0xb1, 0xfd, + 0x28, 0x92, 0x8a, 0x32, 0xd9, 0x47, 0xcc, 0x51, 0x5f, 0xe4, 0x29, 0x7e, 0x10, 0x8d, 0xc6, 0x18, + 0x61, 0x0d, 0xc4, 0xc9, 0x4e, 0x1b, 0xb9, 0x3b, 0xb8, 0x49, 0x5f, 0x40, 0x72, 0xa2, 0x41, 0xa2, + 0xf4, 0x4b, 0x27, 0x14, 0x21, 0x85, 0x01, 0x2f, 0xec, 0x72, 0x60, 0xc1, 0x9b, 0x2e, 0x63, 0x20, + 0x35, 0xe5, 0x4b, 0xd5, 0x26, 0x96, 0x4a, 0x0d, 0xf3, 0x0c, 0xd5, 0xf7, 0x3c, 0xab, 0xef, 0x90, + 0x87, 0xac, 0xcd, 0x7b, 0x06, 0x3d, 0x38, 0x5f, 0xfa, 0x83, 0x03, 0x60, 0xf0, 0x9d, 0x08, 0x2f, + 0x83, 0xd5, 0x4a, 0x51, 0x57, 0x8d, 0x62, 0x49, 0xcf, 0x17, 0x0b, 0xc6, 0x9d, 0x42, 0xb9, 0xa4, + 0x6e, 0xe7, 0x6f, 0xe6, 0xd5, 0x1c, 0x1f, 0x49, 0x2f, 0x76, 0x7b, 0x52, 0x82, 0x3a, 0xaa, 0x9e, + 0x08, 0x94, 0xc1, 0x62, 0xd8, 0xfb, 0x9e, 0x5a, 0xe6, 0xb9, 0xf4, 0x7c, 0xb7, 0x27, 0xc5, 0xa9, + 0xd7, 0x3d, 0xe4, 0xc2, 0x4b, 0x60, 0x29, 0xec, 0x93, 0x55, 0xca, 0x7a, 0x36, 0x5f, 0xe0, 0xa3, + 0xe9, 0x73, 0xdd, 0x9e, 0x34, 0x4f, 0xfd, 0xb2, 0x6c, 0x15, 0x4a, 0x60, 0x21, 0xec, 0x5b, 0x28, + 0xf2, 0x53, 0xe9, 0x64, 0xb7, 0x27, 0xcd, 0x51, 0xb7, 0x02, 0x86, 0x9b, 0x20, 0x35, 0xec, 0x61, + 0xdc, 0xcd, 0xeb, 0xb7, 0x8c, 0x8a, 0xaa, 0x17, 0xf9, 0x58, 0x7a, 0xb9, 0xdb, 0x93, 0xf8, 0xc0, + 0x37, 0xd8, 0x5b, 0xe9, 0xd8, 0xc3, 0x6f, 0x85, 0xc8, 0xa5, 0x9f, 0xa2, 0x60, 0x61, 0xf8, 0xd3, + 0x06, 0x66, 0xc0, 0x85, 0x92, 0x56, 0x2c, 0x15, 0xcb, 0xd9, 0xdb, 0x46, 0x59, 0xcf, 0xea, 0x77, + 0xca, 0x23, 0x09, 0xfb, 0xa9, 0x50, 0xe7, 0x82, 0xd5, 0x84, 0xd7, 0x81, 0x30, 0xea, 0x9f, 0x53, + 0x4b, 0xc5, 0x72, 0x5e, 0x37, 0x4a, 0xaa, 0x96, 0x2f, 0xe6, 0x78, 0x2e, 0xbd, 0xda, 0xed, 0x49, + 0x4b, 0x14, 0x32, 0x34, 0x54, 0xf0, 0x6d, 0xf0, 0x9f, 0x51, 0x70, 0xa5, 0xa8, 0xe7, 0x0b, 0xef, + 0x05, 0xd8, 0x68, 0x7a, 0xa5, 0xdb, 0x93, 0x20, 0xc5, 0x56, 0x42, 0x13, 0x00, 0x2f, 0x83, 0x95, + 0x51, 0x68, 0x29, 0x5b, 0x2e, 0xab, 0x39, 0x7e, 0x2a, 0xcd, 0x77, 0x7b, 0x52, 0x92, 0x62, 0x4a, + 0xa6, 0xeb, 0xa2, 0x3a, 0xbc, 0x0a, 0x52, 0xa3, 0xde, 0x9a, 0xfa, 0xbe, 0xba, 0xad, 0xab, 0x39, + 0x3e, 0x96, 0x86, 0xdd, 0x9e, 0xb4, 0x40, 0xfd, 0x35, 0xf4, 0x11, 0xaa, 0x11, 0x74, 0x2a, 0xff, + 0xcd, 0x6c, 0xfe, 0xb6, 0x9a, 0xe3, 0xa7, 0xc3, 0xfc, 0x37, 0x4d, 0xab, 0x89, 0xea, 0xb4, 0x9c, + 0x4a, 0xe1, 0xe0, 0x85, 0x10, 0x79, 0xf6, 0x42, 0x88, 0x7c, 0x7e, 0x28, 0x44, 0x0e, 0x0e, 0x05, + 0xee, 0xe9, 0xa1, 0xc0, 0xfd, 0x7e, 0x28, 0x70, 0x8f, 0x5e, 0x0a, 0x91, 0xa7, 0x2f, 0x85, 0xc8, + 0xb3, 0x97, 0x42, 0xe4, 0xfe, 0xdf, 0x2f, 0xc4, 0x3d, 0xff, 0x3f, 0x35, 0xbf, 0x9f, 0xab, 0x33, + 0xfe, 0x0e, 0x79, 0xfd, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd7, 0x68, 0xea, 0xf2, 0xc4, 0x0d, + 0x00, 0x00, } func (this *TextProposal) Equal(that interface{}) bool { @@ -667,6 +709,44 @@ func (this *TallyResult) Equal(that interface{}) bool { } return true } +func (m *SubVote) 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 *SubVote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SubVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.Rate.Size() + i -= size + if _, err := m.Rate.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintGov(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if m.Option != 0 { + i = encodeVarintGov(dAtA, i, uint64(m.Option)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func (m *TextProposal) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -937,23 +1017,19 @@ func (m *Vote) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.Options) > 0 { - dAtA8 := make([]byte, len(m.Options)*10) - var j7 int - for _, num := range m.Options { - for num >= 1<<7 { - dAtA8[j7] = uint8(uint64(num)&0x7f | 0x80) - num >>= 7 - j7++ - } - dAtA8[j7] = uint8(num) - j7++ - } - i -= j7 - copy(dAtA[i:], dAtA8[:j7]) - i = encodeVarintGov(dAtA, i, uint64(j7)) - i-- - dAtA[i] = 0x1a + if len(m.SubVotes) > 0 { + for iNdEx := len(m.SubVotes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.SubVotes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGov(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } } if len(m.Voter) > 0 { i -= len(m.Voter) @@ -990,12 +1066,12 @@ func (m *DepositParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - n9, err9 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.MaxDepositPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.MaxDepositPeriod):]) - if err9 != nil { - return 0, err9 + n7, err7 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.MaxDepositPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.MaxDepositPeriod):]) + if err7 != nil { + return 0, err7 } - i -= n9 - i = encodeVarintGov(dAtA, i, uint64(n9)) + i -= n7 + i = encodeVarintGov(dAtA, i, uint64(n7)) i-- dAtA[i] = 0x12 if len(m.MinDeposit) > 0 { @@ -1035,12 +1111,12 @@ func (m *VotingParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - n10, err10 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.VotingPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.VotingPeriod):]) - if err10 != nil { - return 0, err10 + n8, err8 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.VotingPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.VotingPeriod):]) + if err8 != nil { + return 0, err8 } - i -= n10 - i = encodeVarintGov(dAtA, i, uint64(n10)) + i -= n8 + i = encodeVarintGov(dAtA, i, uint64(n8)) i-- dAtA[i] = 0xa return len(dAtA) - i, nil @@ -1110,6 +1186,20 @@ func encodeVarintGov(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } +func (m *SubVote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Option != 0 { + n += 1 + sovGov(uint64(m.Option)) + } + l = m.Rate.Size() + n += 1 + l + sovGov(uint64(l)) + return n +} + func (m *TextProposal) Size() (n int) { if m == nil { return 0 @@ -1214,12 +1304,11 @@ func (m *Vote) Size() (n int) { if l > 0 { n += 1 + l + sovGov(uint64(l)) } - if len(m.Options) > 0 { - l = 0 - for _, e := range m.Options { - l += sovGov(uint64(e)) + if len(m.SubVotes) > 0 { + for _, e := range m.SubVotes { + l = e.Size() + n += 1 + l + sovGov(uint64(l)) } - n += 1 + sovGov(uint64(l)) + l } return n } @@ -1273,6 +1362,112 @@ func sovGov(x uint64) (n int) { func sozGov(x uint64) (n int) { return sovGov(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } +func (m *SubVote) 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 ErrIntOverflowGov + } + 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: SubVote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SubVote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Option", wireType) + } + m.Option = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Option |= VoteOption(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Rate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Rate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGov(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGov + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthGov + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *TextProposal) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -2124,74 +2319,39 @@ func (m *Vote) Unmarshal(dAtA []byte) error { m.Voter = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: - if wireType == 0 { - var v VoteOption - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGov - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= VoteOption(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.Options = append(m.Options, v) - } else if wireType == 2 { - var packedLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGov - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - packedLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if packedLen < 0 { - return ErrInvalidLengthGov - } - postIndex := iNdEx + packedLen - if postIndex < 0 { - return ErrInvalidLengthGov - } - if postIndex > l { + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SubVotes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGov + } + if iNdEx >= l { return io.ErrUnexpectedEOF } - var elementCount int - if elementCount != 0 && len(m.Options) == 0 { - m.Options = make([]VoteOption, 0, elementCount) - } - for iNdEx < postIndex { - var v VoteOption - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGov - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= VoteOption(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.Options = append(m.Options, v) - } - } else { - return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType) + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } } + if msglen < 0 { + return ErrInvalidLengthGov + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGov + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SubVotes = append(m.SubVotes, SubVote{}) + if err := m.SubVotes[len(m.SubVotes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGov(dAtA[iNdEx:]) diff --git a/x/gov/types/msgs.go b/x/gov/types/msgs.go index e97c25ce8f01..354cbaef24cf 100644 --- a/x/gov/types/msgs.go +++ b/x/gov/types/msgs.go @@ -177,8 +177,8 @@ func (msg MsgDeposit) GetSigners() []sdk.AccAddress { // NewMsgVote creates a message to cast a vote on an active proposal //nolint:interfacer -func NewMsgVote(voter sdk.AccAddress, proposalID uint64, option VoteOption) *MsgVote { - return &MsgVote{proposalID, voter.String(), option} +func NewMsgVote(voter sdk.AccAddress, proposalID uint64, subVotes []SubVote) *MsgVote { + return &MsgVote{proposalID, voter.String(), subVotes} } // Route implements Msg @@ -192,8 +192,10 @@ func (msg MsgVote) ValidateBasic() error { if msg.Voter == "" { return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Voter) } - if !ValidVoteOption(msg.Option) { - return sdkerrors.Wrap(ErrInvalidVote, msg.Option.String()) + for _, subvote := range msg.SubVotes { + if !ValidSubVote(subvote) { + return sdkerrors.Wrap(ErrInvalidVote, subvote.String()) + } } return nil diff --git a/x/gov/types/tx.pb.go b/x/gov/types/tx.pb.go index c4d9a9670153..f595a954a2a3 100644 --- a/x/gov/types/tx.pb.go +++ b/x/gov/types/tx.pb.go @@ -119,9 +119,9 @@ func (m *MsgSubmitProposalResponse) GetProposalId() uint64 { // MsgVote defines a message to cast a vote. type MsgVote struct { - ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id" yaml:"proposal_id"` - Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` - Option VoteOption `protobuf:"varint,3,opt,name=option,proto3,enum=cosmos.gov.v1beta1.VoteOption" json:"option,omitempty"` + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id" yaml:"proposal_id"` + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` + SubVotes []SubVote `protobuf:"bytes,3,rep,name=sub_votes,json=subVotes,proto3" json:"sub_votes"` } func (m *MsgVote) Reset() { *m = MsgVote{} } @@ -281,44 +281,45 @@ func init() { func init() { proto.RegisterFile("cosmos/gov/v1beta1/tx.proto", fileDescriptor_3c053992595e3dce) } var fileDescriptor_3c053992595e3dce = []byte{ - // 586 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xbf, 0x6f, 0xd3, 0x40, - 0x14, 0xb6, 0x93, 0xd2, 0xd0, 0x8b, 0x94, 0xd2, 0x53, 0x84, 0x12, 0xb7, 0xb2, 0x23, 0xa3, 0xa2, - 0x2c, 0xb1, 0x69, 0x90, 0x18, 0xca, 0x44, 0x8a, 0x10, 0x20, 0x45, 0x80, 0x91, 0x18, 0x58, 0x22, - 0xdb, 0x71, 0x8d, 0x45, 0xe2, 0x67, 0xe5, 0x2e, 0x51, 0xb3, 0x31, 0x22, 0x06, 0x60, 0x64, 0xcc, - 0xcc, 0x86, 0xc4, 0x1f, 0x51, 0x31, 0x75, 0x64, 0x40, 0x01, 0x25, 0x0b, 0x30, 0xf6, 0x2f, 0x40, - 0xbe, 0x1f, 0x69, 0xd5, 0xa4, 0x01, 0xa4, 0x4e, 0xc9, 0x7b, 0xdf, 0xfb, 0x3e, 0xdd, 0xf7, 0xdd, - 0xf3, 0xa1, 0x4d, 0x1f, 0x48, 0x17, 0x88, 0x1d, 0xc2, 0xc0, 0x1e, 0xec, 0x78, 0x01, 0x75, 0x77, - 0x6c, 0x7a, 0x60, 0x25, 0x3d, 0xa0, 0x80, 0x31, 0x07, 0xad, 0x10, 0x06, 0x96, 0x00, 0x35, 0x5d, - 0x10, 0x3c, 0x97, 0x04, 0x33, 0x86, 0x0f, 0x51, 0xcc, 0x39, 0xda, 0xd6, 0x02, 0xc1, 0x94, 0xcf, - 0xd1, 0x32, 0x47, 0x5b, 0xac, 0xb2, 0x85, 0x3c, 0x87, 0x8a, 0x21, 0x84, 0xc0, 0xfb, 0xe9, 0x3f, - 0x49, 0x08, 0x01, 0xc2, 0x4e, 0x60, 0xb3, 0xca, 0xeb, 0xef, 0xdb, 0x6e, 0x3c, 0xe4, 0x90, 0xf9, - 0x2e, 0x83, 0x36, 0x9a, 0x24, 0x7c, 0xda, 0xf7, 0xba, 0x11, 0x7d, 0xdc, 0x83, 0x04, 0x88, 0xdb, - 0xc1, 0xb7, 0x51, 0xce, 0x87, 0x98, 0x06, 0x31, 0x2d, 0xa9, 0x15, 0xb5, 0x9a, 0xaf, 0x17, 0x2d, - 0x2e, 0x61, 0x49, 0x09, 0xeb, 0x4e, 0x3c, 0x6c, 0xe4, 0xbf, 0x7c, 0xae, 0xe5, 0xf6, 0xf8, 0xa0, - 0x23, 0x19, 0xf8, 0xad, 0x8a, 0xd6, 0xa3, 0x38, 0xa2, 0x91, 0xdb, 0x69, 0xb5, 0x83, 0x04, 0x48, - 0x44, 0x4b, 0x99, 0x4a, 0xb6, 0x9a, 0xaf, 0x97, 0x2d, 0x71, 0xd8, 0xd4, 0xb7, 0x0c, 0xc3, 0xda, - 0x83, 0x28, 0x6e, 0x3c, 0x3c, 0x1c, 0x1b, 0xca, 0xf1, 0xd8, 0xb8, 0x3a, 0x74, 0xbb, 0x9d, 0x5d, - 0xf3, 0x0c, 0xdf, 0xfc, 0xf8, 0xdd, 0xa8, 0x86, 0x11, 0x7d, 0xd1, 0xf7, 0x2c, 0x1f, 0xba, 0xc2, - 0xb3, 0xf8, 0xa9, 0x91, 0xf6, 0x4b, 0x9b, 0x0e, 0x93, 0x80, 0x30, 0x29, 0xe2, 0x14, 0x04, 0xfb, - 0x2e, 0x27, 0x63, 0x0d, 0x5d, 0x4e, 0x98, 0xb3, 0xa0, 0x57, 0xca, 0x56, 0xd4, 0xea, 0x9a, 0x33, - 0xab, 0x77, 0xaf, 0xbc, 0x1e, 0x19, 0xca, 0x87, 0x91, 0xa1, 0xfc, 0x1c, 0x19, 0xca, 0xab, 0x6f, - 0x15, 0xc5, 0xf4, 0x51, 0x79, 0x2e, 0x10, 0x27, 0x20, 0x09, 0xc4, 0x24, 0xc0, 0xf7, 0x50, 0x3e, - 0x11, 0xbd, 0x56, 0xd4, 0x66, 0xe1, 0xac, 0x34, 0xb6, 0x7f, 0x8f, 0x8d, 0xd3, 0xed, 0xe3, 0xb1, - 0x81, 0xb9, 0x8d, 0x53, 0x4d, 0xd3, 0x41, 0xb2, 0x7a, 0xd0, 0x36, 0x3f, 0xa9, 0x28, 0xd7, 0x24, - 0xe1, 0x33, 0xa0, 0x17, 0xa6, 0x89, 0x8b, 0xe8, 0xd2, 0x00, 0x68, 0xd0, 0x2b, 0x65, 0x98, 0x47, - 0x5e, 0xe0, 0x5b, 0x68, 0x15, 0x12, 0x1a, 0x41, 0xcc, 0xac, 0x17, 0xea, 0xba, 0x35, 0xbf, 0x8f, - 0x56, 0x7a, 0x8e, 0x47, 0x6c, 0xca, 0x11, 0xd3, 0x0b, 0x82, 0xd9, 0x40, 0xeb, 0xe2, 0xc8, 0x32, - 0x0e, 0xf3, 0x97, 0x8a, 0x50, 0x93, 0x84, 0x32, 0xe8, 0x8b, 0x72, 0xb2, 0x85, 0xd6, 0xc4, 0xc5, - 0x83, 0x74, 0x73, 0xd2, 0xc0, 0x3e, 0x5a, 0x75, 0xbb, 0xd0, 0x8f, 0x69, 0x29, 0xfb, 0xb7, 0xad, - 0xba, 0x91, 0x6e, 0xd5, 0x7f, 0xed, 0x8e, 0x90, 0x5e, 0x60, 0xbf, 0x88, 0xf0, 0x89, 0x55, 0x99, - 0x40, 0xfd, 0x4d, 0x06, 0x65, 0x9b, 0x24, 0xc4, 0xfb, 0xa8, 0x70, 0xe6, 0x1b, 0xda, 0x5e, 0x14, - 0xf4, 0xdc, 0x66, 0x69, 0xb5, 0x7f, 0x1a, 0x9b, 0x2d, 0xe0, 0x7d, 0xb4, 0xc2, 0x96, 0x66, 0xf3, - 0x1c, 0x5a, 0x0a, 0x6a, 0xd7, 0x96, 0x80, 0x33, 0xa5, 0x27, 0x28, 0x27, 0xef, 0x4d, 0x3f, 0x67, - 0x5e, 0xe0, 0xda, 0xf5, 0xe5, 0xb8, 0x94, 0x6c, 0x34, 0x0e, 0x27, 0xba, 0x7a, 0x34, 0xd1, 0xd5, - 0x1f, 0x13, 0x5d, 0x7d, 0x3f, 0xd5, 0x95, 0xa3, 0xa9, 0xae, 0x7c, 0x9d, 0xea, 0xca, 0xf3, 0xe5, - 0x17, 0x70, 0xc0, 0x1e, 0x3a, 0x76, 0x0d, 0xde, 0x2a, 0x7b, 0x61, 0x6e, 0xfe, 0x09, 0x00, 0x00, - 0xff, 0xff, 0x7f, 0x09, 0x3f, 0x57, 0x54, 0x05, 0x00, 0x00, + // 593 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x31, 0x6f, 0xd3, 0x40, + 0x14, 0xb6, 0x93, 0xd2, 0xb4, 0x17, 0xa9, 0xa5, 0xa7, 0x08, 0x25, 0x4e, 0x65, 0x47, 0x46, 0x45, + 0x59, 0x62, 0xd3, 0xb0, 0x15, 0x09, 0x09, 0x17, 0x21, 0x40, 0x8a, 0x04, 0xae, 0xc4, 0xc0, 0x12, + 0xd9, 0x8e, 0x6b, 0x2c, 0x12, 0x3f, 0x2b, 0x77, 0x8e, 0x9a, 0x8d, 0x11, 0x31, 0x00, 0x23, 0x63, + 0x66, 0x66, 0x16, 0xfe, 0x41, 0xc5, 0xd4, 0x91, 0x01, 0x05, 0x94, 0x2c, 0xc0, 0xd8, 0x5f, 0x80, + 0xec, 0xbb, 0x4b, 0xab, 0x26, 0x8d, 0x40, 0xea, 0x94, 0xbc, 0xf7, 0xdd, 0xf7, 0xe9, 0xbe, 0xef, + 0x3d, 0x1f, 0xaa, 0x7a, 0x40, 0x7a, 0x40, 0xcc, 0x00, 0x06, 0xe6, 0x60, 0xd7, 0xf5, 0xa9, 0xb3, + 0x6b, 0xd2, 0x23, 0x23, 0xee, 0x03, 0x05, 0x8c, 0x19, 0x68, 0x04, 0x30, 0x30, 0x38, 0xa8, 0xa8, + 0x9c, 0xe0, 0x3a, 0xc4, 0x9f, 0x31, 0x3c, 0x08, 0x23, 0xc6, 0x51, 0xb6, 0x17, 0x08, 0xa6, 0x7c, + 0x86, 0x56, 0x18, 0xda, 0xce, 0x2a, 0x93, 0xcb, 0x33, 0xa8, 0x14, 0x40, 0x00, 0xac, 0x9f, 0xfe, + 0x13, 0x84, 0x00, 0x20, 0xe8, 0xfa, 0x66, 0x56, 0xb9, 0xc9, 0xa1, 0xe9, 0x44, 0x43, 0x06, 0xe9, + 0xef, 0x73, 0x68, 0xab, 0x45, 0x82, 0x83, 0xc4, 0xed, 0x85, 0xf4, 0x69, 0x1f, 0x62, 0x20, 0x4e, + 0x17, 0xdf, 0x45, 0x05, 0x0f, 0x22, 0xea, 0x47, 0xb4, 0x2c, 0xd7, 0xe4, 0x7a, 0xb1, 0x59, 0x32, + 0x98, 0x84, 0x21, 0x24, 0x8c, 0xfb, 0xd1, 0xd0, 0x2a, 0x7e, 0xfd, 0xdc, 0x28, 0xec, 0xb3, 0x83, + 0xb6, 0x60, 0xe0, 0x77, 0x32, 0xda, 0x0c, 0xa3, 0x90, 0x86, 0x4e, 0xb7, 0xdd, 0xf1, 0x63, 0x20, + 0x21, 0x2d, 0xe7, 0x6a, 0xf9, 0x7a, 0xb1, 0x59, 0x31, 0xf8, 0x65, 0x53, 0xdf, 0x22, 0x0c, 0x63, + 0x1f, 0xc2, 0xc8, 0x7a, 0x72, 0x3c, 0xd6, 0xa4, 0xd3, 0xb1, 0x76, 0x63, 0xe8, 0xf4, 0xba, 0x7b, + 0xfa, 0x05, 0xbe, 0xfe, 0xe9, 0x87, 0x56, 0x0f, 0x42, 0xfa, 0x32, 0x71, 0x0d, 0x0f, 0x7a, 0xdc, + 0x33, 0xff, 0x69, 0x90, 0xce, 0x2b, 0x93, 0x0e, 0x63, 0x9f, 0x64, 0x52, 0xc4, 0xde, 0xe0, 0xec, + 0x07, 0x8c, 0x8c, 0x15, 0xb4, 0x16, 0x67, 0xce, 0xfc, 0x7e, 0x39, 0x5f, 0x93, 0xeb, 0xeb, 0xf6, + 0xac, 0xde, 0xbb, 0xfe, 0x66, 0xa4, 0x49, 0x1f, 0x47, 0x9a, 0xf4, 0x6b, 0xa4, 0x49, 0xaf, 0xbf, + 0xd7, 0x24, 0xdd, 0x43, 0x95, 0xb9, 0x40, 0x6c, 0x9f, 0xc4, 0x10, 0x11, 0x1f, 0x3f, 0x44, 0xc5, + 0x98, 0xf7, 0xda, 0x61, 0x27, 0x0b, 0x67, 0xc5, 0xda, 0xf9, 0x33, 0xd6, 0xce, 0xb7, 0x4f, 0xc7, + 0x1a, 0x66, 0x36, 0xce, 0x35, 0x75, 0x1b, 0x89, 0xea, 0x71, 0x47, 0xff, 0x22, 0xa3, 0x42, 0x8b, + 0x04, 0xcf, 0x81, 0x5e, 0x99, 0x26, 0x2e, 0xa1, 0x6b, 0x03, 0xa0, 0x7e, 0xbf, 0x9c, 0xcb, 0x3c, + 0xb2, 0x02, 0xdf, 0x43, 0xeb, 0x24, 0x71, 0xdb, 0x69, 0x41, 0xca, 0xf9, 0x6c, 0x0c, 0x55, 0x63, + 0x7e, 0x25, 0x8d, 0x83, 0xc4, 0x4d, 0x6f, 0x63, 0xad, 0xa4, 0x83, 0xb0, 0xd7, 0x08, 0x2b, 0xc9, + 0x82, 0x80, 0xb6, 0xd0, 0x26, 0xbf, 0xba, 0x88, 0x45, 0xff, 0x2d, 0x23, 0xd4, 0x22, 0x81, 0x08, + 0xfc, 0xaa, 0x1c, 0x6d, 0xa3, 0x75, 0xbe, 0x00, 0x20, 0x5c, 0x9d, 0x35, 0xb0, 0x87, 0x56, 0x9d, + 0x1e, 0x24, 0x11, 0xe5, 0xb6, 0x96, 0x6c, 0xd7, 0xed, 0xd4, 0xd4, 0x7f, 0xed, 0x10, 0x97, 0x5e, + 0x60, 0xbf, 0x84, 0xf0, 0x99, 0x55, 0x91, 0x40, 0xf3, 0x6d, 0x0e, 0xe5, 0x5b, 0x24, 0xc0, 0x87, + 0x68, 0xe3, 0xc2, 0xb7, 0xb4, 0xb3, 0x28, 0xed, 0xb9, 0x0d, 0x53, 0x1a, 0xff, 0x74, 0x6c, 0xb6, + 0x88, 0x8f, 0xd0, 0x4a, 0xb6, 0x3c, 0xd5, 0x4b, 0x68, 0x29, 0xa8, 0xdc, 0x5c, 0x02, 0xce, 0x94, + 0x9e, 0xa1, 0x82, 0x98, 0x9b, 0x7a, 0xc9, 0x79, 0x8e, 0x2b, 0xb7, 0x96, 0xe3, 0x42, 0xd2, 0xb2, + 0x8e, 0x27, 0xaa, 0x7c, 0x32, 0x51, 0xe5, 0x9f, 0x13, 0x55, 0xfe, 0x30, 0x55, 0xa5, 0x93, 0xa9, + 0x2a, 0x7d, 0x9b, 0xaa, 0xd2, 0x8b, 0xe5, 0x03, 0x38, 0xca, 0x1e, 0xbc, 0x6c, 0x0c, 0xee, 0x6a, + 0xf6, 0xd2, 0xdc, 0xf9, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x7e, 0x2c, 0x84, 0x48, 0x5c, 0x05, 0x00, + 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -583,10 +584,19 @@ func (m *MsgVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.Option != 0 { - i = encodeVarintTx(dAtA, i, uint64(m.Option)) - i-- - dAtA[i] = 0x18 + if len(m.SubVotes) > 0 { + for iNdEx := len(m.SubVotes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.SubVotes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } } if len(m.Voter) > 0 { i -= len(m.Voter) @@ -757,8 +767,11 @@ func (m *MsgVote) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - if m.Option != 0 { - n += 1 + sovTx(uint64(m.Option)) + if len(m.SubVotes) > 0 { + for _, e := range m.SubVotes { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } } return n } @@ -1117,10 +1130,10 @@ func (m *MsgVote) Unmarshal(dAtA []byte) error { m.Voter = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Option", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SubVotes", wireType) } - m.Option = 0 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -1130,11 +1143,26 @@ func (m *MsgVote) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Option |= VoteOption(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SubVotes = append(m.SubVotes, SubVote{}) + if err := m.SubVotes[len(m.SubVotes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) diff --git a/x/gov/types/vote.go b/x/gov/types/vote.go index 363887a289da..fbeb86606f93 100644 --- a/x/gov/types/vote.go +++ b/x/gov/types/vote.go @@ -1,6 +1,7 @@ package types import ( + "encoding/json" "fmt" yaml "gopkg.in/yaml.v2" @@ -10,8 +11,8 @@ import ( // NewVote creates a new Vote instance //nolint:interfacer -func NewVote(proposalID uint64, voter sdk.AccAddress, option VoteOption) Vote { - return Vote{proposalID, voter.String(), option} +func NewVote(proposalID uint64, voter sdk.AccAddress, subvotes []SubVote) Vote { + return Vote{proposalID, voter.String(), subvotes} } func (v Vote) String() string { @@ -43,7 +44,7 @@ func (v Votes) String() string { } out := fmt.Sprintf("Votes for Proposal %d:", v[0].ProposalId) for _, vot := range v { - out += fmt.Sprintf("\n %s: %s", vot.Voter, vot.Option) + out += fmt.Sprintf("\n %s: %s", vot.Voter, vot.SubVotes) } return out } @@ -53,6 +54,25 @@ func (v Vote) Empty() bool { return v.String() == Vote{}.String() } +// NewSubVote creates a new Vote instance +//nolint:interfacer +func NewSubVote(option VoteOption, rate int64) SubVote { + return SubVote{option, sdk.NewDec(rate)} +} + +func (v SubVote) String() string { + out, _ := json.Marshal(v) + return string(out) +} + +// ValidSubVote returns true if the sub vote is valid and false otherwise. +func ValidSubVote(subvote SubVote) bool { + if !subvote.Rate.IsPositive() { + return false + } + return ValidVoteOption(subvote.Option) +} + // VoteOptionFromString returns a VoteOption from a string. It returns an error // if the string is invalid. func VoteOptionFromString(str string) (VoteOption, error) { From c50478448919bcaafa256c9adad1c1e76afa0103 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Wed, 28 Oct 2020 22:05:35 +1000 Subject: [PATCH 003/152] Fix build errors and tests after struct modification --- x/gov/abci_test.go | 4 +- x/gov/client/cli/cli_test.go | 3 +- x/gov/client/cli/tx.go | 2 +- x/gov/client/rest/grpc_query_test.go | 3 +- x/gov/client/rest/tx.go | 2 +- x/gov/client/utils/query_test.go | 22 ++++---- x/gov/keeper/grpc_query_test.go | 20 ++++---- x/gov/keeper/proposal_test.go | 2 +- x/gov/keeper/querier_test.go | 8 +-- x/gov/keeper/tally.go | 32 +++++++++--- x/gov/keeper/tally_test.go | 77 ++++++++++++++-------------- x/gov/keeper/vote.go | 10 ++-- x/gov/keeper/vote_test.go | 27 ++++++---- x/gov/legacy/v040/migrate.go | 2 +- x/gov/simulation/decoder_test.go | 2 +- x/gov/simulation/operations.go | 2 +- x/gov/simulation/operations_test.go | 3 +- x/gov/types/events.go | 1 + x/gov/types/msgs_test.go | 2 +- x/gov/types/tally.go | 6 +-- x/gov/types/vote.go | 8 +++ 21 files changed, 137 insertions(+), 101 deletions(-) diff --git a/x/gov/abci_test.go b/x/gov/abci_test.go index bfda1b3590b6..30a3afe3bc73 100644 --- a/x/gov/abci_test.go +++ b/x/gov/abci_test.go @@ -307,7 +307,7 @@ func TestProposalPassedEndblocker(t *testing.T) { deposits := initialModuleAccCoins.Add(proposal.TotalDeposit...).Add(proposalCoins...) require.True(t, moduleAccCoins.IsEqual(deposits)) - err = app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.OptionYes) + err = app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)}) require.NoError(t, err) newHeader := ctx.BlockHeader() @@ -348,7 +348,7 @@ func TestEndBlockerProposalHandlerFailed(t *testing.T) { handleAndCheck(t, gov.NewHandler(app.GovKeeper), ctx, newDepositMsg) - err = app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.OptionYes) + err = app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)}) require.NoError(t, err) newHeader := ctx.BlockHeader() diff --git a/x/gov/client/cli/cli_test.go b/x/gov/client/cli/cli_test.go index c1367eabe074..ec2ebfd92cc6 100644 --- a/x/gov/client/cli/cli_test.go +++ b/x/gov/client/cli/cli_test.go @@ -735,7 +735,8 @@ func (s *IntegrationTestSuite) TestCmdQueryVote() { var vote types.Vote s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &vote), out.String()) - s.Require().Equal(types.OptionYes, vote.Option) + s.Require().True(len(vote.SubVotes) == 1) + s.Require().Equal(types.OptionYes, vote.SubVotes[0].Option) } }) } diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 5f04d9184c2a..bda8cf9e6fa2 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -237,7 +237,7 @@ $ %s tx gov vote 1 yes --from mykey } // Build vote message and run basic validation - msg := types.NewMsgVote(from, proposalID, byteVoteOption) + msg := types.NewMsgVote(from, proposalID, types.SubVotes{types.NewSubVote(byteVoteOption, 1)}) err = msg.ValidateBasic() if err != nil { return err diff --git a/x/gov/client/rest/grpc_query_test.go b/x/gov/client/rest/grpc_query_test.go index 23a282d5d311..b9a4c764022c 100644 --- a/x/gov/client/rest/grpc_query_test.go +++ b/x/gov/client/rest/grpc_query_test.go @@ -193,7 +193,8 @@ func (s *IntegrationTestSuite) TestGetProposalVoteGRPC() { } else { s.Require().NoError(err) s.Require().NotEmpty(vote.Vote) - s.Require().Equal(types.OptionYes, vote.Vote.Option) + s.Require().True(len(vote.Vote.SubVotes) == 1) + s.Require().Equal(types.OptionYes, vote.Vote.SubVotes[0].Option) } }) } diff --git a/x/gov/client/rest/tx.go b/x/gov/client/rest/tx.go index 4f010f27b7d3..e427fbf7a72a 100644 --- a/x/gov/client/rest/tx.go +++ b/x/gov/client/rest/tx.go @@ -117,7 +117,7 @@ func newVoteHandlerFn(clientCtx client.Context) http.HandlerFunc { } // create the message - msg := types.NewMsgVote(req.Voter, proposalID, []types.SubVote{types.NewSubVote(voteOption, 1)}) + msg := types.NewMsgVote(req.Voter, proposalID, types.SubVotes{types.NewSubVote(voteOption, 1)}) if rest.CheckBadRequestError(w, msg.ValidateBasic()) { return } diff --git a/x/gov/client/utils/query_test.go b/x/gov/client/utils/query_test.go index c6f999e86ee6..8f792ff1a214 100644 --- a/x/gov/client/utils/query_test.go +++ b/x/gov/client/utils/query_test.go @@ -70,12 +70,12 @@ func TestGetPaginatedVotes(t *testing.T) { acc2 := make(sdk.AccAddress, 20) acc2[0] = 2 acc1Msgs := []sdk.Msg{ - types.NewMsgVote(acc1, 0, types.OptionYes), - types.NewMsgVote(acc1, 0, types.OptionYes), + types.NewMsgVote(acc1, 0, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), + types.NewMsgVote(acc1, 0, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), } acc2Msgs := []sdk.Msg{ - types.NewMsgVote(acc2, 0, types.OptionYes), - types.NewMsgVote(acc2, 0, types.OptionYes), + types.NewMsgVote(acc2, 0, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), + types.NewMsgVote(acc2, 0, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), } for _, tc := range []testCase{ { @@ -87,8 +87,8 @@ func TestGetPaginatedVotes(t *testing.T) { acc2Msgs[:1], }, votes: []types.Vote{ - types.NewVote(0, acc1, types.OptionYes), - types.NewVote(0, acc2, types.OptionYes)}, + types.NewVote(0, acc1, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), + types.NewVote(0, acc2, types.SubVotes{types.NewSubVote(types.OptionYes, 1)})}, }, { description: "2MsgPerTx1Chunk", @@ -99,8 +99,8 @@ func TestGetPaginatedVotes(t *testing.T) { acc2Msgs, }, votes: []types.Vote{ - types.NewVote(0, acc1, types.OptionYes), - types.NewVote(0, acc1, types.OptionYes)}, + types.NewVote(0, acc1, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), + types.NewVote(0, acc1, types.SubVotes{types.NewSubVote(types.OptionYes, 1)})}, }, { description: "2MsgPerTx2Chunk", @@ -111,8 +111,8 @@ func TestGetPaginatedVotes(t *testing.T) { acc2Msgs, }, votes: []types.Vote{ - types.NewVote(0, acc2, types.OptionYes), - types.NewVote(0, acc2, types.OptionYes)}, + types.NewVote(0, acc2, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), + types.NewVote(0, acc2, types.SubVotes{types.NewSubVote(types.OptionYes, 1)})}, }, { description: "IncompleteSearchTx", @@ -121,7 +121,7 @@ func TestGetPaginatedVotes(t *testing.T) { msgs: [][]sdk.Msg{ acc1Msgs[:1], }, - votes: []types.Vote{types.NewVote(0, acc1, types.OptionYes)}, + votes: []types.Vote{types.NewVote(0, acc1, types.SubVotes{types.NewSubVote(types.OptionYes, 1)})}, }, { description: "InvalidPage", diff --git a/x/gov/keeper/grpc_query_test.go b/x/gov/keeper/grpc_query_test.go index dc330d734829..a170c0c0e0b5 100644 --- a/x/gov/keeper/grpc_query_test.go +++ b/x/gov/keeper/grpc_query_test.go @@ -183,7 +183,7 @@ func (suite *KeeperTestSuite) TestGRPCQueryProposals() { func() { testProposals[1].Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, testProposals[1]) - suite.Require().NoError(app.GovKeeper.AddVote(ctx, testProposals[1].ProposalId, addrs[0], types.OptionAbstain)) + suite.Require().NoError(app.GovKeeper.AddVote(ctx, testProposals[1].ProposalId, addrs[0], types.SubVotes{types.NewSubVote(types.OptionAbstain, 1)})) req = &types.QueryProposalsRequest{ Voter: addrs[0].String(), @@ -291,14 +291,14 @@ func (suite *KeeperTestSuite) TestGRPCQueryVote() { func() { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.OptionAbstain)) + suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.SubVotes{types.NewSubVote(types.OptionAbstain, 1)})) req = &types.QueryVoteRequest{ ProposalId: proposal.ProposalId, Voter: addrs[0].String(), } - expRes = &types.QueryVoteResponse{Vote: types.NewVote(proposal.ProposalId, addrs[0], types.OptionAbstain)} + expRes = &types.QueryVoteResponse{Vote: types.NewVote(proposal.ProposalId, addrs[0], types.SubVotes{types.NewSubVote(types.OptionAbstain, 1)})} }, true, }, @@ -395,15 +395,15 @@ func (suite *KeeperTestSuite) TestGRPCQueryVotes() { app.GovKeeper.SetProposal(ctx, proposal) votes = []types.Vote{ - {proposal.ProposalId, addrs[0].String(), types.OptionAbstain}, - {proposal.ProposalId, addrs[1].String(), types.OptionYes}, + {proposal.ProposalId, addrs[0].String(), types.SubVotes{types.NewSubVote(types.OptionAbstain, 1)}}, + {proposal.ProposalId, addrs[1].String(), types.SubVotes{types.NewSubVote(types.OptionYes, 1)}}, } accAddr1, err1 := sdk.AccAddressFromBech32(votes[0].Voter) accAddr2, err2 := sdk.AccAddressFromBech32(votes[1].Voter) suite.Require().NoError(err1) suite.Require().NoError(err2) - suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, accAddr1, votes[0].Option)) - suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, accAddr2, votes[1].Option)) + suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, accAddr1, votes[0].SubVotes)) + suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, accAddr2, votes[1].SubVotes)) req = &types.QueryVotesRequest{ ProposalId: proposal.ProposalId, @@ -769,9 +769,9 @@ func (suite *KeeperTestSuite) TestGRPCQueryTally() { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.OptionYes)) - suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[1], types.OptionYes)) - suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[2], types.OptionYes)) + suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[1], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[2], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) req = &types.QueryTallyResultRequest{ProposalId: proposal.ProposalId} diff --git a/x/gov/keeper/proposal_test.go b/x/gov/keeper/proposal_test.go index 1a833737d940..c6c2d803761c 100644 --- a/x/gov/keeper/proposal_test.go +++ b/x/gov/keeper/proposal_test.go @@ -101,7 +101,7 @@ func TestGetProposalsFiltered(t *testing.T) { if i%2 == 0 { d := types.NewDeposit(proposalID, addr1, nil) - v := types.NewVote(proposalID, addr1, types.OptionYes) + v := types.NewVote(proposalID, addr1, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}) app.GovKeeper.SetDeposit(ctx, d) app.GovKeeper.SetVote(ctx, v) } diff --git a/x/gov/keeper/querier_test.go b/x/gov/keeper/querier_test.go index 9960fb116bed..3e2345b0c7d6 100644 --- a/x/gov/keeper/querier_test.go +++ b/x/gov/keeper/querier_test.go @@ -251,13 +251,13 @@ func TestQueries(t *testing.T) { require.Equal(t, proposal3, proposals[1]) // Addrs[0] votes on proposals #2 & #3 - vote1 := types.NewVote(proposal2.ProposalId, TestAddrs[0], types.OptionYes) - vote2 := types.NewVote(proposal3.ProposalId, TestAddrs[0], types.OptionYes) + vote1 := types.NewVote(proposal2.ProposalId, TestAddrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)}) + vote2 := types.NewVote(proposal3.ProposalId, TestAddrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)}) app.GovKeeper.SetVote(ctx, vote1) app.GovKeeper.SetVote(ctx, vote2) // Addrs[1] votes on proposal #3 - vote3 := types.NewVote(proposal3.ProposalId, TestAddrs[1], types.OptionYes) + vote3 := types.NewVote(proposal3.ProposalId, TestAddrs[1], types.SubVotes{types.NewSubVote(types.OptionYes, 1)}) app.GovKeeper.SetVote(ctx, vote3) // Test query voted by TestAddrs[0] @@ -323,7 +323,7 @@ func TestPaginatedVotesQuery(t *testing.T) { vote := types.Vote{ ProposalId: proposal.ProposalId, Voter: addr.String(), - Option: types.OptionYes, + SubVotes: types.SubVotes{types.NewSubVote(types.OptionYes, 1)}, } votes[i] = vote app.GovKeeper.SetVote(ctx, vote) diff --git a/x/gov/keeper/tally.go b/x/gov/keeper/tally.go index 796609db5a10..5e7a9923ffdc 100644 --- a/x/gov/keeper/tally.go +++ b/x/gov/keeper/tally.go @@ -27,7 +27,7 @@ func (keeper Keeper) Tally(ctx sdk.Context, proposal types.Proposal) (passes boo validator.GetBondedTokens(), validator.GetDelegatorShares(), sdk.ZeroDec(), - types.OptionEmpty, + types.SubVotes{}, ) return false @@ -43,7 +43,7 @@ func (keeper Keeper) Tally(ctx sdk.Context, proposal types.Proposal) (passes boo valAddrStr := sdk.ValAddress(voter.Bytes()).String() if val, ok := currValidators[valAddrStr]; ok { - val.Vote = vote.Option + val.Vote = vote.SubVotes currValidators[valAddrStr] = val } @@ -60,8 +60,17 @@ func (keeper Keeper) Tally(ctx sdk.Context, proposal types.Proposal) (passes boo delegatorShare := delegation.GetShares().Quo(val.DelegatorShares) votingPower := delegatorShare.MulInt(val.BondedTokens) - results[vote.Option] = results[vote.Option].Add(votingPower) - totalVotingPower = totalVotingPower.Add(votingPower) + totalRates := sdk.NewDec(0) + for _, subvote := range vote.SubVotes { + totalRates = totalRates.Add(subvote.Rate) + } + for _, subvote := range vote.SubVotes { + subPower := sdk.NewDecFromBigInt(votingPower.BigInt().Div(votingPower.Mul(subvote.Rate).BigInt(), totalRates.BigInt())) + results[subvote.Option] = results[subvote.Option].Add(subPower) + totalVotingPower = totalVotingPower.Add(subPower) + } + // TODO how should handle remainder? + // TODO how should handle when totalRates == 0 } return false @@ -73,7 +82,7 @@ func (keeper Keeper) Tally(ctx sdk.Context, proposal types.Proposal) (passes boo // iterate over the validators again to tally their voting power for _, val := range currValidators { - if val.Vote == types.OptionEmpty { + if len(val.Vote) == 0 { continue } @@ -81,8 +90,17 @@ func (keeper Keeper) Tally(ctx sdk.Context, proposal types.Proposal) (passes boo fractionAfterDeductions := sharesAfterDeductions.Quo(val.DelegatorShares) votingPower := fractionAfterDeductions.MulInt(val.BondedTokens) - results[val.Vote] = results[val.Vote].Add(votingPower) - totalVotingPower = totalVotingPower.Add(votingPower) + totalRates := sdk.NewDec(0) + for _, subvote := range val.Vote { + totalRates = totalRates.Add(subvote.Rate) + } + for _, subvote := range val.Vote { + subPower := sdk.NewDecFromBigInt(votingPower.BigInt().Div(votingPower.Mul(subvote.Rate).BigInt(), totalRates.BigInt())) + results[subvote.Option] = results[subvote.Option].Add(subPower) + totalVotingPower = totalVotingPower.Add(subPower) + // TODO how should handle remainder? + // TODO how should handle when totalRates == 0 + } } tallyParams := keeper.GetTallyParams(ctx) diff --git a/x/gov/keeper/tally_test.go b/x/gov/keeper/tally_test.go index 6c23a510e9b0..61e07a8a3e96 100644 --- a/x/gov/keeper/tally_test.go +++ b/x/gov/keeper/tally_test.go @@ -50,7 +50,7 @@ func TestTallyNoQuorum(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - err = app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.OptionYes) + err = app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)}) require.Nil(t, err) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) @@ -73,9 +73,9 @@ func TestTallyOnlyValidatorsAllYes(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.OptionYes)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.OptionYes)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.OptionYes)) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -99,8 +99,8 @@ func TestTallyOnlyValidators51No(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.OptionYes)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.OptionNo)) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -123,8 +123,8 @@ func TestTallyOnlyValidators51Yes(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.OptionNo)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.OptionYes)) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -148,9 +148,9 @@ func TestTallyOnlyValidatorsVetoed(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.OptionYes)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.OptionYes)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[2], types.OptionNoWithVeto)) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[2], types.SubVotes{types.NewSubVote(types.OptionNoWithVeto, 1)})) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -174,9 +174,9 @@ func TestTallyOnlyValidatorsAbstainPasses(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.OptionAbstain)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.OptionNo)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[2], types.OptionYes)) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.SubVotes{types.NewSubVote(types.OptionAbstain, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[2], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -200,9 +200,9 @@ func TestTallyOnlyValidatorsAbstainFails(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.OptionAbstain)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.OptionYes)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[2], types.OptionNo)) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.SubVotes{types.NewSubVote(types.OptionAbstain, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[2], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -227,8 +227,8 @@ func TestTallyOnlyValidatorsNonVoter(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddr1, types.OptionYes)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddr2, types.OptionNo)) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddr1, types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddr2, types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -261,10 +261,10 @@ func TestTallyDelgatorOverride(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.OptionYes)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.OptionYes)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[3], types.OptionYes)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[4], types.OptionNo)) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[3], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[4], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -297,9 +297,9 @@ func TestTallyDelgatorInherit(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.OptionNo)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.OptionNo)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.OptionYes)) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -336,10 +336,10 @@ func TestTallyDelgatorMultipleOverride(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.OptionYes)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.OptionYes)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.OptionYes)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[3], types.OptionNo)) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[3], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -378,9 +378,9 @@ func TestTallyDelgatorMultipleInherit(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.OptionYes)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.OptionNo)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.OptionNo)) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -421,9 +421,8 @@ func TestTallyJailedValidator(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.OptionYes)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.OptionNo)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.OptionNo)) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -454,9 +453,9 @@ func TestTallyValidatorMultipleDelegations(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.OptionYes)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.OptionNo)) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.OptionYes)) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) diff --git a/x/gov/keeper/vote.go b/x/gov/keeper/vote.go index c86a06872a30..4a298697f519 100644 --- a/x/gov/keeper/vote.go +++ b/x/gov/keeper/vote.go @@ -9,7 +9,7 @@ import ( ) // AddVote adds a vote on a specific proposal -func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress, subvotes []types.SubVote) error { +func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress, subvotes types.SubVotes) error { proposal, ok := keeper.GetProposal(ctx, proposalID) if !ok { return sdkerrors.Wrapf(types.ErrUnknownProposal, "%d", proposalID) @@ -18,8 +18,10 @@ func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.A return sdkerrors.Wrapf(types.ErrInactiveProposal, "%d", proposalID) } - if !types.ValidVoteOption(option) { - return sdkerrors.Wrap(types.ErrInvalidVote, option.String()) + for _, subvote := range subvotes { + if !types.ValidSubVote(subvote) { + return sdkerrors.Wrap(types.ErrInvalidVote, subvote.String()) + } } vote := types.NewVote(proposalID, voterAddr, subvotes) @@ -28,7 +30,7 @@ func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.A ctx.EventManager().EmitEvent( sdk.NewEvent( types.EventTypeProposalVote, - sdk.NewAttribute(types.AttributeKeyOption, option.String()), + sdk.NewAttribute(types.AttributeKeyOption, subvotes.String()), sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposalID)), ), ) diff --git a/x/gov/keeper/vote_test.go b/x/gov/keeper/vote_test.go index 5f5bf0cc73a4..6c9a78da45c9 100644 --- a/x/gov/keeper/vote_test.go +++ b/x/gov/keeper/vote_test.go @@ -24,37 +24,40 @@ func TestVotes(t *testing.T) { var invalidOption types.VoteOption = 0x10 - require.Error(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.OptionYes), "proposal not on voting period") - require.Error(t, app.GovKeeper.AddVote(ctx, 10, addrs[0], types.OptionYes), "invalid proposal ID") + require.Error(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), "proposal not on voting period") + require.Error(t, app.GovKeeper.AddVote(ctx, 10, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), "invalid proposal ID") proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.Error(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], invalidOption), "invalid option") + require.Error(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(invalidOption, 1)}), "invalid option") // Test first vote - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.OptionAbstain)) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionAbstain, 1)})) vote, found := app.GovKeeper.GetVote(ctx, proposalID, addrs[0]) require.True(t, found) require.Equal(t, addrs[0].String(), vote.Voter) require.Equal(t, proposalID, vote.ProposalId) - require.Equal(t, types.OptionAbstain, vote.Option) + require.True(t, len(vote.SubVotes) == 1) + require.Equal(t, types.OptionAbstain, vote.SubVotes[0].Option) // Test change of vote - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.OptionYes)) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) vote, found = app.GovKeeper.GetVote(ctx, proposalID, addrs[0]) require.True(t, found) require.Equal(t, addrs[0].String(), vote.Voter) require.Equal(t, proposalID, vote.ProposalId) - require.Equal(t, types.OptionYes, vote.Option) + require.True(t, len(vote.SubVotes) == 1) + require.Equal(t, types.OptionYes, vote.SubVotes[0].Option) // Test second vote - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.OptionNoWithVeto)) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{types.NewSubVote(types.OptionNoWithVeto, 1)})) vote, found = app.GovKeeper.GetVote(ctx, proposalID, addrs[1]) require.True(t, found) require.Equal(t, addrs[1].String(), vote.Voter) require.Equal(t, proposalID, vote.ProposalId) - require.Equal(t, types.OptionNoWithVeto, vote.Option) + require.True(t, len(vote.SubVotes) == 1) + require.Equal(t, types.OptionNoWithVeto, vote.SubVotes[0].Option) // Test vote iterator // NOTE order of deposits is determined by the addresses @@ -63,8 +66,10 @@ func TestVotes(t *testing.T) { require.Equal(t, votes, app.GovKeeper.GetVotes(ctx, proposalID)) require.Equal(t, addrs[0].String(), votes[0].Voter) require.Equal(t, proposalID, votes[0].ProposalId) - require.Equal(t, types.OptionYes, votes[0].Option) + require.True(t, len(votes[0].SubVotes) == 1) + require.Equal(t, types.OptionYes, votes[0].SubVotes[0].Option) require.Equal(t, addrs[1].String(), votes[1].Voter) require.Equal(t, proposalID, votes[1].ProposalId) - require.Equal(t, types.OptionNoWithVeto, votes[1].Option) + require.True(t, len(votes[1].SubVotes) == 1) + require.Equal(t, types.OptionNoWithVeto, votes[1].SubVotes[0].Option) } diff --git a/x/gov/legacy/v040/migrate.go b/x/gov/legacy/v040/migrate.go index 522bbd54ca17..bafd933229fc 100644 --- a/x/gov/legacy/v040/migrate.go +++ b/x/gov/legacy/v040/migrate.go @@ -118,7 +118,7 @@ func Migrate(oldGovState v036gov.GenesisState) *v040gov.GenesisState { newVotes[i] = v040gov.Vote{ ProposalId: oldVote.ProposalID, Voter: oldVote.Voter.String(), - SubVotes: []v040gov.SubVote{v040gov.NewSubVote(migrateVoteOption(oldVote.Option), 1)}, + SubVotes: v040gov.SubVotes{v040gov.NewSubVote(migrateVoteOption(oldVote.Option), 1)}, } } diff --git a/x/gov/simulation/decoder_test.go b/x/gov/simulation/decoder_test.go index 7a5b0fc1bc9d..4a17cb9a57c6 100644 --- a/x/gov/simulation/decoder_test.go +++ b/x/gov/simulation/decoder_test.go @@ -34,7 +34,7 @@ func TestDecodeStore(t *testing.T) { proposalIDBz := make([]byte, 8) binary.LittleEndian.PutUint64(proposalIDBz, 1) deposit := types.NewDeposit(1, delAddr1, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt()))) - vote := types.NewVote(1, delAddr1, types.OptionYes) + vote := types.NewVote(1, delAddr1, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}) proposalBz, err := cdc.MarshalBinaryBare(&proposal) require.NoError(t, err) diff --git a/x/gov/simulation/operations.go b/x/gov/simulation/operations.go index 0dedf648889e..c7c7b6aa6261 100644 --- a/x/gov/simulation/operations.go +++ b/x/gov/simulation/operations.go @@ -281,7 +281,7 @@ func operationSimulateMsgVote(ak types.AccountKeeper, bk types.BankKeeper, k kee } option := randomVotingOption(r) - msg := types.NewMsgVote(simAccount.Address, proposalID, option) + msg := types.NewMsgVote(simAccount.Address, proposalID, types.SubVotes{types.NewSubVote(option, 1)}) account := ak.GetAccount(ctx, simAccount.Address) spendable := bk.SpendableCoins(ctx, account.GetAddress()) diff --git a/x/gov/simulation/operations_test.go b/x/gov/simulation/operations_test.go index 9c6e8306f821..5273de46ac62 100644 --- a/x/gov/simulation/operations_test.go +++ b/x/gov/simulation/operations_test.go @@ -202,7 +202,8 @@ func TestSimulateMsgVote(t *testing.T) { require.True(t, operationMsg.OK) require.Equal(t, uint64(1), msg.ProposalId) require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Voter) - require.Equal(t, types.OptionYes, msg.Option) + require.True(t, len(msg.SubVotes) == 1) + require.Equal(t, types.OptionYes, msg.SubVotes[0].Option) require.Equal(t, "gov", msg.Route()) require.Equal(t, types.TypeMsgVote, msg.Type()) diff --git a/x/gov/types/events.go b/x/gov/types/events.go index 19f8857f3a1c..3f3e471cb1a5 100644 --- a/x/gov/types/events.go +++ b/x/gov/types/events.go @@ -10,6 +10,7 @@ const ( AttributeKeyProposalResult = "proposal_result" AttributeKeyOption = "option" + AttributeKeySubVotes = "sub_votes" AttributeKeyProposalID = "proposal_id" AttributeKeyVotingPeriodStart = "voting_period_start" AttributeValueCategory = "governance" diff --git a/x/gov/types/msgs_test.go b/x/gov/types/msgs_test.go index 9d7d6a36828a..9ae733a9dd44 100644 --- a/x/gov/types/msgs_test.go +++ b/x/gov/types/msgs_test.go @@ -109,7 +109,7 @@ func TestMsgVote(t *testing.T) { } for i, tc := range tests { - msg := NewMsgVote(tc.voterAddr, tc.proposalID, tc.option) + msg := NewMsgVote(tc.voterAddr, tc.proposalID, SubVotes{NewSubVote(tc.option, 1)}) if tc.expectPass { require.Nil(t, msg.ValidateBasic(), "test: %v", i) } else { diff --git a/x/gov/types/tally.go b/x/gov/types/tally.go index a4e9ee908608..294de078d23b 100644 --- a/x/gov/types/tally.go +++ b/x/gov/types/tally.go @@ -12,19 +12,19 @@ type ValidatorGovInfo struct { BondedTokens sdk.Int // Power of a Validator DelegatorShares sdk.Dec // Total outstanding delegator shares DelegatorDeductions sdk.Dec // Delegator deductions from validator's delegators voting independently - Vote VoteOption // Vote of the validator + Vote SubVotes // Vote of the validator } // NewValidatorGovInfo creates a ValidatorGovInfo instance func NewValidatorGovInfo(address sdk.ValAddress, bondedTokens sdk.Int, delegatorShares, - delegatorDeductions sdk.Dec, vote VoteOption) ValidatorGovInfo { + delegatorDeductions sdk.Dec, subvotes SubVotes) ValidatorGovInfo { return ValidatorGovInfo{ Address: address, BondedTokens: bondedTokens, DelegatorShares: delegatorShares, DelegatorDeductions: delegatorDeductions, - Vote: vote, + Vote: subvotes, } } diff --git a/x/gov/types/vote.go b/x/gov/types/vote.go index fbeb86606f93..eb721f1d6f98 100644 --- a/x/gov/types/vote.go +++ b/x/gov/types/vote.go @@ -65,6 +65,14 @@ func (v SubVote) String() string { return string(out) } +// SubVotes describes array of SubVote +type SubVotes []SubVote + +func (v SubVotes) String() string { + out, _ := json.Marshal(v) + return string(out) +} + // ValidSubVote returns true if the sub vote is valid and false otherwise. func ValidSubVote(subvote SubVote) bool { if !subvote.Rate.IsPositive() { From 0cb2c70b4d85e67ad308d054ba831d3880debd14 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Thu, 29 Oct 2020 19:26:51 +1000 Subject: [PATCH 004/152] add subvotes parser from string --- x/gov/client/cli/tx.go | 9 ++++----- x/gov/client/utils/utils.go | 20 +++++++++++++++++++- x/gov/types/vote.go | 26 ++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index bda8cf9e6fa2..35ece9fdc382 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -207,9 +207,8 @@ func NewCmdVote() *cobra.Command { fmt.Sprintf(`Submit a vote for an active proposal. You can find the proposal-id by running "%s query gov proposals". - Example: -$ %s tx gov vote 1 yes --from mykey +$ %s tx gov vote 1 yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05 --from mykey `, version.AppName, version.AppName, ), @@ -230,14 +229,14 @@ $ %s tx gov vote 1 yes --from mykey return fmt.Errorf("proposal-id %s not a valid int, please input a valid proposal-id", args[0]) } - // Find out which vote option user chose - byteVoteOption, err := types.VoteOptionFromString(govutils.NormalizeVoteOption(args[1])) + // Figure out which subvotes user chose + subvotes, err := types.SubVotesFromString(govutils.NormalizeSubVotes(args[1])) if err != nil { return err } // Build vote message and run basic validation - msg := types.NewMsgVote(from, proposalID, types.SubVotes{types.NewSubVote(byteVoteOption, 1)}) + msg := types.NewMsgVote(from, proposalID, subvotes) err = msg.ValidateBasic() if err != nil { return err diff --git a/x/gov/client/utils/utils.go b/x/gov/client/utils/utils.go index 84c2884d1a7f..7a4658ddbb9e 100644 --- a/x/gov/client/utils/utils.go +++ b/x/gov/client/utils/utils.go @@ -1,6 +1,10 @@ package utils -import "github.com/cosmos/cosmos-sdk/x/gov/types" +import ( + "strings" + + "github.com/cosmos/cosmos-sdk/x/gov/types" +) // NormalizeVoteOption - normalize user specified vote option func NormalizeVoteOption(option string) string { @@ -22,6 +26,20 @@ func NormalizeVoteOption(option string) string { } } +// NormalizeSubVotes - normalize subvotes +func NormalizeSubVotes(subvotes string) string { + var newSubVotes []string + for _, subvote := range strings.Split(subvotes, ",") { + fields := strings.Split(subvote, "=") + fields[0] = NormalizeVoteOption(fields[0]) + if len(fields) < 2 { + fields = append(fields, "1") + } + newSubVotes = append(newSubVotes, strings.Join(fields, "=")) + } + return strings.Join(newSubVotes, ",") +} + //NormalizeProposalType - normalize user specified proposal type func NormalizeProposalType(proposalType string) string { switch proposalType { diff --git a/x/gov/types/vote.go b/x/gov/types/vote.go index eb721f1d6f98..ce8e94d50ab6 100644 --- a/x/gov/types/vote.go +++ b/x/gov/types/vote.go @@ -3,6 +3,7 @@ package types import ( "encoding/json" "fmt" + "strings" yaml "gopkg.in/yaml.v2" @@ -91,6 +92,31 @@ func VoteOptionFromString(str string) (VoteOption, error) { return VoteOption(option), nil } +// SubVotesFromString returns a SubVotes from a string. It returns an error +// if the string is invalid. +func SubVotesFromString(str string) (SubVotes, error) { + var subvotes SubVotes + for _, subvote := range strings.Split(str, ",") { + fields := strings.Split(subvote, "=") + option, err := VoteOptionFromString(fields[0]) + if err != nil { + return subvotes, err + } + if len(fields) < 2 { + return subvotes, fmt.Errorf("rate field does not exist for %s opion", fields[0]) + } + rate, err := sdk.NewDecFromStr(fields[1]) + if err != nil { + return subvotes, err + } + subvotes = append(subvotes, SubVote{ + option, + rate, + }) + } + return subvotes, nil +} + // ValidVoteOption returns true if the vote option is valid and false otherwise. func ValidVoteOption(option VoteOption) bool { if option == OptionYes || From 7e87b5d9987dfa7fbeff0104b13f8aa9b11f19de Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Thu, 29 Oct 2020 22:24:55 +1000 Subject: [PATCH 005/152] add cli, grpc, keeper test for new split vote --- x/gov/client/cli/cli_test.go | 66 +++++++++++++++++++++++++--- x/gov/client/rest/grpc_query_test.go | 40 ++++++++++++++--- x/gov/client/rest/rest.go | 6 +-- x/gov/client/rest/tx.go | 7 +-- x/gov/keeper/vote_test.go | 25 ++++++++--- 5 files changed, 119 insertions(+), 25 deletions(-) diff --git a/x/gov/client/cli/cli_test.go b/x/gov/client/cli/cli_test.go index ec2ebfd92cc6..0f79ed97d3e9 100644 --- a/x/gov/client/cli/cli_test.go +++ b/x/gov/client/cli/cli_test.go @@ -33,7 +33,7 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") s.cfg = network.DefaultConfig() - s.cfg.NumValidators = 1 + s.cfg.NumValidators = 2 s.network = network.New(s.T(), s.cfg) @@ -41,6 +41,7 @@ func (s *IntegrationTestSuite) SetupSuite() { s.Require().NoError(err) val := s.network.Validators[0] + val2 := s.network.Validators[1] // create a proposal with deposit _, err = govtestutil.MsgSubmitProposal(val.ClientCtx, val.Address.String(), @@ -54,6 +55,10 @@ func (s *IntegrationTestSuite) SetupSuite() { _, err = govtestutil.MsgVote(val.ClientCtx, val.Address.String(), "1", "yes") s.Require().NoError(err) + // vote for proposal as val2 + _, err = govtestutil.MsgVote(val2.ClientCtx, val2.Address.String(), "1", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05") + s.Require().NoError(err) + // create a proposal without deposit _, err = govtestutil.MsgSubmitProposal(val.ClientCtx, val.Address.String(), "Text Proposal 2", "Where is the title!?", types.ProposalTypeText) @@ -679,7 +684,7 @@ func (s *IntegrationTestSuite) TestCmdQueryVotes() { var votes types.QueryVotesResponse s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &votes), out.String()) - s.Require().Len(votes.Votes, 1) + s.Require().Len(votes.Votes, 2) } }) } @@ -687,11 +692,13 @@ func (s *IntegrationTestSuite) TestCmdQueryVotes() { func (s *IntegrationTestSuite) TestCmdQueryVote() { val := s.network.Validators[0] + val2 := s.network.Validators[1] testCases := []struct { - name string - args []string - expectErr bool + name string + args []string + expectErr bool + expSubVotes types.SubVotes }{ { "get vote of non existing proposal", @@ -700,6 +707,7 @@ func (s *IntegrationTestSuite) TestCmdQueryVote() { val.Address.String(), }, true, + types.SubVotes{types.NewSubVote(types.OptionYes, 1)}, }, { "get vote by wrong voter", @@ -708,6 +716,7 @@ func (s *IntegrationTestSuite) TestCmdQueryVote() { "wrong address", }, true, + types.SubVotes{types.NewSubVote(types.OptionYes, 1)}, }, { "vote for valid proposal", @@ -717,6 +726,22 @@ func (s *IntegrationTestSuite) TestCmdQueryVote() { fmt.Sprintf("--%s=json", tmcli.OutputFlag), }, false, + types.SubVotes{types.NewSubVote(types.OptionYes, 1)}, + }, + { + "split vote for valid proposal", + []string{ + "1", + val2.Address.String(), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + false, + types.SubVotes{ + types.SubVote{Option: types.OptionYes, Rate: sdk.NewDecWithPrec(60, 2)}, + types.SubVote{Option: types.OptionNo, Rate: sdk.NewDecWithPrec(30, 2)}, + types.SubVote{Option: types.OptionAbstain, Rate: sdk.NewDecWithPrec(5, 2)}, + types.SubVote{Option: types.OptionNoWithVeto, Rate: sdk.NewDecWithPrec(5, 2)}, + }, }, } @@ -735,8 +760,11 @@ func (s *IntegrationTestSuite) TestCmdQueryVote() { var vote types.Vote s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &vote), out.String()) - s.Require().True(len(vote.SubVotes) == 1) - s.Require().Equal(types.OptionYes, vote.SubVotes[0].Option) + s.Require().Equal(len(vote.SubVotes), len(tc.expSubVotes)) + for i, subvote := range tc.expSubVotes { + s.Require().Equal(subvote.Option, vote.SubVotes[i].Option) + s.Require().True(subvote.Rate.Equal(vote.SubVotes[i].Rate)) + } } }) } @@ -780,6 +808,30 @@ func (s *IntegrationTestSuite) TestNewCmdVote() { }, false, 0, }, + { + "invalid valid split vote string", + []string{ + "1", + fmt.Sprintf("%s", "yes/0.6,no/0.3,abstain/0.05,no_with_veto/0.05"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + true, 0, + }, + { + "valid split vote", + []string{ + "1", + fmt.Sprintf("%s", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + false, 0, + }, } for _, tc := range testCases { diff --git a/x/gov/client/rest/grpc_query_test.go b/x/gov/client/rest/grpc_query_test.go index b9a4c764022c..276fa1749edc 100644 --- a/x/gov/client/rest/grpc_query_test.go +++ b/x/gov/client/rest/grpc_query_test.go @@ -30,7 +30,7 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") s.cfg = network.DefaultConfig() - s.cfg.NumValidators = 1 + s.cfg.NumValidators = 2 s.network = network.New(s.T(), s.cfg) @@ -38,6 +38,7 @@ func (s *IntegrationTestSuite) SetupSuite() { s.Require().NoError(err) val := s.network.Validators[0] + val2 := s.network.Validators[1] // create a proposal with deposit _, err = govtestutil.MsgSubmitProposal(val.ClientCtx, val.Address.String(), @@ -51,6 +52,10 @@ func (s *IntegrationTestSuite) SetupSuite() { _, err = govtestutil.MsgVote(val.ClientCtx, val.Address.String(), "1", "yes") s.Require().NoError(err) + // vote for proposal as val2 + _, err = govtestutil.MsgVote(val2.ClientCtx, val2.Address.String(), "1", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05") + s.Require().NoError(err) + // create a proposal without deposit _, err = govtestutil.MsgSubmitProposal(val.ClientCtx, val.Address.String(), "Text Proposal 2", "Where is the title!?", types.ProposalTypeText) @@ -149,33 +154,51 @@ func (s *IntegrationTestSuite) TestGetProposalsGRPC() { func (s *IntegrationTestSuite) TestGetProposalVoteGRPC() { val := s.network.Validators[0] + val2 := s.network.Validators[1] voterAddressBase64 := val.Address.String() + voter2AddressBase64 := val2.Address.String() testCases := []struct { - name string - url string - expErr bool + name string + url string + expErr bool + expSubVotes types.SubVotes }{ { "empty proposal", fmt.Sprintf("%s/cosmos/gov/v1beta1/proposals/%s/votes/%s", val.APIAddress, "", voterAddressBase64), true, + types.SubVotes{types.NewSubVote(types.OptionYes, 1)}, }, { "get non existing proposal", fmt.Sprintf("%s/cosmos/gov/v1beta1/proposals/%s/votes/%s", val.APIAddress, "10", voterAddressBase64), true, + types.SubVotes{types.NewSubVote(types.OptionYes, 1)}, }, { "get proposal with wrong voter address", fmt.Sprintf("%s/cosmos/gov/v1beta1/proposals/%s/votes/%s", val.APIAddress, "1", "wrongVoterAddress"), true, + types.SubVotes{types.NewSubVote(types.OptionYes, 1)}, }, { "get proposal with id", fmt.Sprintf("%s/cosmos/gov/v1beta1/proposals/%s/votes/%s", val.APIAddress, "1", voterAddressBase64), false, + types.SubVotes{types.NewSubVote(types.OptionYes, 1)}, + }, + { + "get proposal with id for split vote", + fmt.Sprintf("%s/cosmos/gov/v1beta1/proposals/%s/votes/%s", val.APIAddress, "1", voter2AddressBase64), + false, + types.SubVotes{ + types.SubVote{Option: types.OptionYes, Rate: sdk.NewDecWithPrec(60, 2)}, + types.SubVote{Option: types.OptionNo, Rate: sdk.NewDecWithPrec(30, 2)}, + types.SubVote{Option: types.OptionAbstain, Rate: sdk.NewDecWithPrec(5, 2)}, + types.SubVote{Option: types.OptionNoWithVeto, Rate: sdk.NewDecWithPrec(5, 2)}, + }, }, } @@ -193,8 +216,11 @@ func (s *IntegrationTestSuite) TestGetProposalVoteGRPC() { } else { s.Require().NoError(err) s.Require().NotEmpty(vote.Vote) - s.Require().True(len(vote.Vote.SubVotes) == 1) - s.Require().Equal(types.OptionYes, vote.Vote.SubVotes[0].Option) + s.Require().Equal(len(vote.Vote.SubVotes), len(tc.expSubVotes)) + for i, subvote := range tc.expSubVotes { + s.Require().Equal(subvote.Option, vote.Vote.SubVotes[i].Option) + s.Require().True(subvote.Rate.Equal(vote.Vote.SubVotes[i].Rate)) + } } }) } @@ -233,7 +259,7 @@ func (s *IntegrationTestSuite) TestGetProposalVotesGRPC() { s.Require().Error(err) } else { s.Require().NoError(err) - s.Require().Len(votes.Votes, 1) + s.Require().Len(votes.Votes, 2) } }) } diff --git a/x/gov/client/rest/rest.go b/x/gov/client/rest/rest.go index 5136e19ea1f5..b7375e7e1876 100644 --- a/x/gov/client/rest/rest.go +++ b/x/gov/client/rest/rest.go @@ -52,7 +52,7 @@ type DepositReq struct { // VoteReq defines the properties of a vote request's body. type VoteReq struct { - BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` - Voter sdk.AccAddress `json:"voter" yaml:"voter"` // address of the voter - Option string `json:"option" yaml:"option"` // option from OptionSet chosen by the voter + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + Voter sdk.AccAddress `json:"voter" yaml:"voter"` // address of the voter + SubVotes string `json:"sub_votes" yaml:"sub_votes"` // option from OptionSet chosen by the voter } diff --git a/x/gov/client/rest/tx.go b/x/gov/client/rest/tx.go index e427fbf7a72a..3c481660e1e1 100644 --- a/x/gov/client/rest/tx.go +++ b/x/gov/client/rest/tx.go @@ -111,13 +111,14 @@ func newVoteHandlerFn(clientCtx client.Context) http.HandlerFunc { return } - voteOption, err := types.VoteOptionFromString(gcutils.NormalizeVoteOption(req.Option)) - if rest.CheckBadRequestError(w, err) { + // Figure out which subvotes user chose + subvotes, err := types.SubVotesFromString(gcutils.NormalizeSubVotes(req.SubVotes)) + if err != nil { return } // create the message - msg := types.NewMsgVote(req.Voter, proposalID, types.SubVotes{types.NewSubVote(voteOption, 1)}) + msg := types.NewMsgVote(req.Voter, proposalID, subvotes) if rest.CheckBadRequestError(w, msg.ValidateBasic()) { return } diff --git a/x/gov/keeper/vote_test.go b/x/gov/keeper/vote_test.go index 6c9a78da45c9..dd7dc34a5739 100644 --- a/x/gov/keeper/vote_test.go +++ b/x/gov/keeper/vote_test.go @@ -51,13 +51,25 @@ func TestVotes(t *testing.T) { require.Equal(t, types.OptionYes, vote.SubVotes[0].Option) // Test second vote - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{types.NewSubVote(types.OptionNoWithVeto, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{ + types.SubVote{Option: types.OptionYes, Rate: sdk.NewDecWithPrec(60, 2)}, + types.SubVote{Option: types.OptionNo, Rate: sdk.NewDecWithPrec(30, 2)}, + types.SubVote{Option: types.OptionAbstain, Rate: sdk.NewDecWithPrec(5, 2)}, + types.SubVote{Option: types.OptionNoWithVeto, Rate: sdk.NewDecWithPrec(5, 2)}, + })) vote, found = app.GovKeeper.GetVote(ctx, proposalID, addrs[1]) require.True(t, found) require.Equal(t, addrs[1].String(), vote.Voter) require.Equal(t, proposalID, vote.ProposalId) - require.True(t, len(vote.SubVotes) == 1) - require.Equal(t, types.OptionNoWithVeto, vote.SubVotes[0].Option) + require.True(t, len(vote.SubVotes) == 4) + require.Equal(t, types.OptionYes, vote.SubVotes[0].Option) + require.Equal(t, types.OptionNo, vote.SubVotes[1].Option) + require.Equal(t, types.OptionAbstain, vote.SubVotes[2].Option) + require.Equal(t, types.OptionNoWithVeto, vote.SubVotes[3].Option) + require.True(t, vote.SubVotes[0].Rate.Equal(sdk.NewDecWithPrec(60, 2))) + require.True(t, vote.SubVotes[1].Rate.Equal(sdk.NewDecWithPrec(30, 2))) + require.True(t, vote.SubVotes[2].Rate.Equal(sdk.NewDecWithPrec(5, 2))) + require.True(t, vote.SubVotes[3].Rate.Equal(sdk.NewDecWithPrec(5, 2))) // Test vote iterator // NOTE order of deposits is determined by the addresses @@ -70,6 +82,9 @@ func TestVotes(t *testing.T) { require.Equal(t, types.OptionYes, votes[0].SubVotes[0].Option) require.Equal(t, addrs[1].String(), votes[1].Voter) require.Equal(t, proposalID, votes[1].ProposalId) - require.True(t, len(votes[1].SubVotes) == 1) - require.Equal(t, types.OptionNoWithVeto, votes[1].SubVotes[0].Option) + require.True(t, len(votes[1].SubVotes) == 4) + require.True(t, votes[1].SubVotes[0].Rate.Equal(sdk.NewDecWithPrec(60, 2))) + require.True(t, votes[1].SubVotes[1].Rate.Equal(sdk.NewDecWithPrec(30, 2))) + require.True(t, votes[1].SubVotes[2].Rate.Equal(sdk.NewDecWithPrec(5, 2))) + require.True(t, votes[1].SubVotes[3].Rate.Equal(sdk.NewDecWithPrec(5, 2))) } From e7d35490685ebda14542596a168d04193df3bf7f Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Thu, 29 Oct 2020 22:30:42 +1000 Subject: [PATCH 006/152] fix lint issues --- x/gov/client/utils/utils.go | 2 +- x/gov/types/vote.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x/gov/client/utils/utils.go b/x/gov/client/utils/utils.go index 7a4658ddbb9e..9ad73522d070 100644 --- a/x/gov/client/utils/utils.go +++ b/x/gov/client/utils/utils.go @@ -28,7 +28,7 @@ func NormalizeVoteOption(option string) string { // NormalizeSubVotes - normalize subvotes func NormalizeSubVotes(subvotes string) string { - var newSubVotes []string + newSubVotes := []string{} for _, subvote := range strings.Split(subvotes, ",") { fields := strings.Split(subvote, "=") fields[0] = NormalizeVoteOption(fields[0]) diff --git a/x/gov/types/vote.go b/x/gov/types/vote.go index ce8e94d50ab6..5a3a399019e5 100644 --- a/x/gov/types/vote.go +++ b/x/gov/types/vote.go @@ -95,7 +95,7 @@ func VoteOptionFromString(str string) (VoteOption, error) { // SubVotesFromString returns a SubVotes from a string. It returns an error // if the string is invalid. func SubVotesFromString(str string) (SubVotes, error) { - var subvotes SubVotes + subvotes := SubVotes{} for _, subvote := range strings.Split(str, ",") { fields := strings.Split(subvote, "=") option, err := VoteOptionFromString(fields[0]) From fe0d0a50450d5ba270a033864dc77681165cfdbf Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Thu, 29 Oct 2020 22:33:24 +1000 Subject: [PATCH 007/152] add comment for SubVote proto --- proto/cosmos/gov/v1beta1/gov.proto | 1 + 1 file changed, 1 insertion(+) diff --git a/proto/cosmos/gov/v1beta1/gov.proto b/proto/cosmos/gov/v1beta1/gov.proto index 196545bc098b..048ad18f6fb0 100644 --- a/proto/cosmos/gov/v1beta1/gov.proto +++ b/proto/cosmos/gov/v1beta1/gov.proto @@ -29,6 +29,7 @@ enum VoteOption { VOTE_OPTION_NO_WITH_VETO = 4 [(gogoproto.enumvalue_customname) = "OptionNoWithVeto"]; } +// SubVote defines a unit of vote for vote split. message SubVote { VoteOption option = 1; string rate = 2 [ From b3d86e1a8db9ed5971110acda584a007768d7d3a Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Thu, 29 Oct 2020 22:43:08 +1000 Subject: [PATCH 008/152] update msg vote validate basic and test --- x/gov/types/msgs.go | 5 +++++ x/gov/types/msgs_test.go | 19 +++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/x/gov/types/msgs.go b/x/gov/types/msgs.go index 354cbaef24cf..49ed6b734d7f 100644 --- a/x/gov/types/msgs.go +++ b/x/gov/types/msgs.go @@ -192,6 +192,11 @@ func (msg MsgVote) ValidateBasic() error { if msg.Voter == "" { return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Voter) } + + if len(msg.SubVotes) == 0 { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, SubVotes(msg.SubVotes).String()) + } + for _, subvote := range msg.SubVotes { if !ValidSubVote(subvote) { return sdkerrors.Wrap(ErrInvalidVote, subvote.String()) diff --git a/x/gov/types/msgs_test.go b/x/gov/types/msgs_test.go index 9ae733a9dd44..a974e4d44efd 100644 --- a/x/gov/types/msgs_test.go +++ b/x/gov/types/msgs_test.go @@ -97,19 +97,22 @@ func TestMsgVote(t *testing.T) { tests := []struct { proposalID uint64 voterAddr sdk.AccAddress - option VoteOption + subvotes SubVotes expectPass bool }{ - {0, addrs[0], OptionYes, true}, - {0, sdk.AccAddress{}, OptionYes, false}, - {0, addrs[0], OptionNo, true}, - {0, addrs[0], OptionNoWithVeto, true}, - {0, addrs[0], OptionAbstain, true}, - {0, addrs[0], VoteOption(0x13), false}, + {0, addrs[0], SubVotes{NewSubVote(OptionYes, 1)}, true}, + {0, sdk.AccAddress{}, SubVotes{NewSubVote(OptionYes, 1)}, false}, + {0, addrs[0], SubVotes{NewSubVote(OptionNo, 1)}, true}, + {0, addrs[0], SubVotes{NewSubVote(OptionNoWithVeto, 1)}, true}, + {0, addrs[0], SubVotes{NewSubVote(OptionAbstain, 1)}, true}, + {0, addrs[0], SubVotes{NewSubVote(OptionYes, 1), NewSubVote(OptionAbstain, 1)}, true}, + {0, addrs[0], SubVotes{NewSubVote(OptionYes, 0)}, false}, + {0, addrs[0], SubVotes{}, false}, + {0, addrs[0], SubVotes{NewSubVote(VoteOption(0x13), 1)}, false}, } for i, tc := range tests { - msg := NewMsgVote(tc.voterAddr, tc.proposalID, SubVotes{NewSubVote(tc.option, 1)}) + msg := NewMsgVote(tc.voterAddr, tc.proposalID, tc.subvotes) if tc.expectPass { require.Nil(t, msg.ValidateBasic(), "test: %v", i) } else { From a59ac3e31a008d5884664c6e142018a8f18cfdd8 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Thu, 29 Oct 2020 23:52:21 +1000 Subject: [PATCH 009/152] fix integration and rest test --- x/gov/client/cli/cli_test.go | 28 +++++++++++++++++----------- x/gov/client/rest/grpc_query_test.go | 27 ++++++++++++++++----------- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/x/gov/client/cli/cli_test.go b/x/gov/client/cli/cli_test.go index 0f79ed97d3e9..8c049ebd59f6 100644 --- a/x/gov/client/cli/cli_test.go +++ b/x/gov/client/cli/cli_test.go @@ -33,7 +33,7 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") s.cfg = network.DefaultConfig() - s.cfg.NumValidators = 2 + s.cfg.NumValidators = 1 s.network = network.New(s.T(), s.cfg) @@ -41,7 +41,6 @@ func (s *IntegrationTestSuite) SetupSuite() { s.Require().NoError(err) val := s.network.Validators[0] - val2 := s.network.Validators[1] // create a proposal with deposit _, err = govtestutil.MsgSubmitProposal(val.ClientCtx, val.Address.String(), @@ -55,16 +54,24 @@ func (s *IntegrationTestSuite) SetupSuite() { _, err = govtestutil.MsgVote(val.ClientCtx, val.Address.String(), "1", "yes") s.Require().NoError(err) - // vote for proposal as val2 - _, err = govtestutil.MsgVote(val2.ClientCtx, val2.Address.String(), "1", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05") - s.Require().NoError(err) - // create a proposal without deposit _, err = govtestutil.MsgSubmitProposal(val.ClientCtx, val.Address.String(), "Text Proposal 2", "Where is the title!?", types.ProposalTypeText) s.Require().NoError(err) _, err = s.network.WaitForHeight(1) s.Require().NoError(err) + + // create a proposal3 with deposit + _, err = govtestutil.MsgSubmitProposal(val.ClientCtx, val.Address.String(), + "Text Proposal 3", "Where is the title!?", types.ProposalTypeText, + fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, types.DefaultMinDepositTokens).String())) + s.Require().NoError(err) + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) + + // vote for proposal3 as val + _, err = govtestutil.MsgVote(val.ClientCtx, val.Address.String(), "3", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05") + s.Require().NoError(err) } func (s *IntegrationTestSuite) TearDownSuite() { @@ -453,7 +460,7 @@ func (s *IntegrationTestSuite) TestCmdGetProposals() { var proposals types.QueryProposalsResponse s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &proposals), out.String()) - s.Require().Len(proposals.Proposals, 2) + s.Require().Len(proposals.Proposals, 3) } }) } @@ -684,7 +691,7 @@ func (s *IntegrationTestSuite) TestCmdQueryVotes() { var votes types.QueryVotesResponse s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &votes), out.String()) - s.Require().Len(votes.Votes, 2) + s.Require().Len(votes.Votes, 1) } }) } @@ -692,7 +699,6 @@ func (s *IntegrationTestSuite) TestCmdQueryVotes() { func (s *IntegrationTestSuite) TestCmdQueryVote() { val := s.network.Validators[0] - val2 := s.network.Validators[1] testCases := []struct { name string @@ -731,8 +737,8 @@ func (s *IntegrationTestSuite) TestCmdQueryVote() { { "split vote for valid proposal", []string{ - "1", - val2.Address.String(), + "3", + val.Address.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag), }, false, diff --git a/x/gov/client/rest/grpc_query_test.go b/x/gov/client/rest/grpc_query_test.go index 276fa1749edc..2d7a159c5c2e 100644 --- a/x/gov/client/rest/grpc_query_test.go +++ b/x/gov/client/rest/grpc_query_test.go @@ -30,7 +30,7 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") s.cfg = network.DefaultConfig() - s.cfg.NumValidators = 2 + s.cfg.NumValidators = 1 s.network = network.New(s.T(), s.cfg) @@ -38,7 +38,6 @@ func (s *IntegrationTestSuite) SetupSuite() { s.Require().NoError(err) val := s.network.Validators[0] - val2 := s.network.Validators[1] // create a proposal with deposit _, err = govtestutil.MsgSubmitProposal(val.ClientCtx, val.Address.String(), @@ -52,16 +51,24 @@ func (s *IntegrationTestSuite) SetupSuite() { _, err = govtestutil.MsgVote(val.ClientCtx, val.Address.String(), "1", "yes") s.Require().NoError(err) - // vote for proposal as val2 - _, err = govtestutil.MsgVote(val2.ClientCtx, val2.Address.String(), "1", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05") - s.Require().NoError(err) - // create a proposal without deposit _, err = govtestutil.MsgSubmitProposal(val.ClientCtx, val.Address.String(), "Text Proposal 2", "Where is the title!?", types.ProposalTypeText) s.Require().NoError(err) _, err = s.network.WaitForHeight(1) s.Require().NoError(err) + + // create a proposal3 with deposit + _, err = govtestutil.MsgSubmitProposal(val.ClientCtx, val.Address.String(), + "Text Proposal 3", "Where is the title!?", types.ProposalTypeText, + fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, types.DefaultMinDepositTokens).String())) + s.Require().NoError(err) + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) + + // vote for proposal3 as val + _, err = govtestutil.MsgVote(val.ClientCtx, val.Address.String(), "3", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05") + s.Require().NoError(err) } func (s *IntegrationTestSuite) TestGetProposalGRPC() { @@ -146,7 +153,7 @@ func (s *IntegrationTestSuite) TestGetProposalsGRPC() { s.Require().Empty(proposals.Proposals) } else { s.Require().NoError(err) - s.Require().Len(proposals.Proposals, 2) + s.Require().Len(proposals.Proposals, 3) } }) } @@ -154,10 +161,8 @@ func (s *IntegrationTestSuite) TestGetProposalsGRPC() { func (s *IntegrationTestSuite) TestGetProposalVoteGRPC() { val := s.network.Validators[0] - val2 := s.network.Validators[1] voterAddressBase64 := val.Address.String() - voter2AddressBase64 := val2.Address.String() testCases := []struct { name string @@ -191,7 +196,7 @@ func (s *IntegrationTestSuite) TestGetProposalVoteGRPC() { }, { "get proposal with id for split vote", - fmt.Sprintf("%s/cosmos/gov/v1beta1/proposals/%s/votes/%s", val.APIAddress, "1", voter2AddressBase64), + fmt.Sprintf("%s/cosmos/gov/v1beta1/proposals/%s/votes/%s", val.APIAddress, "3", voterAddressBase64), false, types.SubVotes{ types.SubVote{Option: types.OptionYes, Rate: sdk.NewDecWithPrec(60, 2)}, @@ -259,7 +264,7 @@ func (s *IntegrationTestSuite) TestGetProposalVotesGRPC() { s.Require().Error(err) } else { s.Require().NoError(err) - s.Require().Len(votes.Votes, 2) + s.Require().Len(votes.Votes, 1) } }) } From 73c757dc4f60271ff9df33a5611c671ce1b01082 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Fri, 30 Oct 2020 23:14:39 +1000 Subject: [PATCH 010/152] refactor SubVote to WeightedVoteOption && add utility for NewNonSplitVoteOption --- proto/cosmos/gov/v1beta1/gov.proto | 14 +- proto/cosmos/gov/v1beta1/tx.proto | 6 +- x/gov/abci_test.go | 4 +- x/gov/client/cli/cli_test.go | 32 ++-- x/gov/client/cli/tx.go | 6 +- x/gov/client/rest/grpc_query_test.go | 34 ++-- x/gov/client/rest/rest.go | 6 +- x/gov/client/rest/tx.go | 6 +- x/gov/client/utils/query.go | 4 +- x/gov/client/utils/query_test.go | 24 +-- x/gov/client/utils/utils.go | 14 +- x/gov/keeper/grpc_query_test.go | 20 +-- x/gov/keeper/msg_server.go | 2 +- x/gov/keeper/proposal_test.go | 2 +- x/gov/keeper/querier_test.go | 8 +- x/gov/keeper/tally.go | 24 +-- x/gov/keeper/tally_test.go | 76 ++++---- x/gov/keeper/vote.go | 12 +- x/gov/keeper/vote_test.go | 60 +++---- x/gov/legacy/v040/migrate.go | 2 +- x/gov/simulation/decoder_test.go | 2 +- x/gov/simulation/operations.go | 2 +- x/gov/simulation/operations_test.go | 4 +- x/gov/types/events.go | 1 - x/gov/types/gov.pb.go | 260 +++++++++++++-------------- x/gov/types/msgs.go | 25 ++- x/gov/types/msgs_test.go | 34 ++-- x/gov/types/tally.go | 14 +- x/gov/types/tx.pb.go | 100 +++++------ x/gov/types/vote.go | 53 +++--- 30 files changed, 436 insertions(+), 415 deletions(-) diff --git a/proto/cosmos/gov/v1beta1/gov.proto b/proto/cosmos/gov/v1beta1/gov.proto index 048ad18f6fb0..25dd9a68cdb6 100644 --- a/proto/cosmos/gov/v1beta1/gov.proto +++ b/proto/cosmos/gov/v1beta1/gov.proto @@ -29,13 +29,13 @@ enum VoteOption { VOTE_OPTION_NO_WITH_VETO = 4 [(gogoproto.enumvalue_customname) = "OptionNoWithVeto"]; } -// SubVote defines a unit of vote for vote split. -message SubVote { +// WeightedVoteOption defines a unit of vote for vote split. +message WeightedVoteOption { VoteOption option = 1; - string rate = 2 [ + string weight = 2 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false, - (gogoproto.moretags) = "yaml:\"rate\"" + (gogoproto.moretags) = "yaml:\"weight\"" ]; } @@ -129,9 +129,9 @@ message Vote { option (gogoproto.goproto_stringer) = false; option (gogoproto.equal) = false; - uint64 proposal_id = 1 [(gogoproto.moretags) = "yaml:\"proposal_id\""]; - string voter = 2; - repeated SubVote sub_votes = 3 [(gogoproto.nullable) = false]; + uint64 proposal_id = 1 [(gogoproto.moretags) = "yaml:\"proposal_id\""]; + string voter = 2; + repeated WeightedVoteOption options = 3 [(gogoproto.nullable) = false]; } // DepositParams defines the params for deposits on governance proposals. diff --git a/proto/cosmos/gov/v1beta1/tx.proto b/proto/cosmos/gov/v1beta1/tx.proto index d059874f12d7..9d38203b9281 100644 --- a/proto/cosmos/gov/v1beta1/tx.proto +++ b/proto/cosmos/gov/v1beta1/tx.proto @@ -50,9 +50,9 @@ message MsgVote { option (gogoproto.stringer) = false; option (gogoproto.goproto_getters) = false; - uint64 proposal_id = 1 [(gogoproto.jsontag) = "proposal_id", (gogoproto.moretags) = "yaml:\"proposal_id\""]; - string voter = 2; - repeated SubVote sub_votes = 3 [(gogoproto.nullable) = false]; + uint64 proposal_id = 1 [(gogoproto.jsontag) = "proposal_id", (gogoproto.moretags) = "yaml:\"proposal_id\""]; + string voter = 2; + repeated WeightedVoteOption options = 3 [(gogoproto.nullable) = false]; } // MsgVoteResponse defines the Msg/Vote response type. diff --git a/x/gov/abci_test.go b/x/gov/abci_test.go index 30a3afe3bc73..cefd12eedf5a 100644 --- a/x/gov/abci_test.go +++ b/x/gov/abci_test.go @@ -307,7 +307,7 @@ func TestProposalPassedEndblocker(t *testing.T) { deposits := initialModuleAccCoins.Add(proposal.TotalDeposit...).Add(proposalCoins...) require.True(t, moduleAccCoins.IsEqual(deposits)) - err = app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)}) + err = app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.NewNonSplitVoteOption(types.OptionYes)) require.NoError(t, err) newHeader := ctx.BlockHeader() @@ -348,7 +348,7 @@ func TestEndBlockerProposalHandlerFailed(t *testing.T) { handleAndCheck(t, gov.NewHandler(app.GovKeeper), ctx, newDepositMsg) - err = app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)}) + err = app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.NewNonSplitVoteOption(types.OptionYes)) require.NoError(t, err) newHeader := ctx.BlockHeader() diff --git a/x/gov/client/cli/cli_test.go b/x/gov/client/cli/cli_test.go index 8c049ebd59f6..0ccac645a6ec 100644 --- a/x/gov/client/cli/cli_test.go +++ b/x/gov/client/cli/cli_test.go @@ -701,10 +701,10 @@ func (s *IntegrationTestSuite) TestCmdQueryVote() { val := s.network.Validators[0] testCases := []struct { - name string - args []string - expectErr bool - expSubVotes types.SubVotes + name string + args []string + expectErr bool + expVoteOptions types.WeightedVoteOptions }{ { "get vote of non existing proposal", @@ -713,7 +713,7 @@ func (s *IntegrationTestSuite) TestCmdQueryVote() { val.Address.String(), }, true, - types.SubVotes{types.NewSubVote(types.OptionYes, 1)}, + types.NewNonSplitVoteOption(types.OptionYes), }, { "get vote by wrong voter", @@ -722,7 +722,7 @@ func (s *IntegrationTestSuite) TestCmdQueryVote() { "wrong address", }, true, - types.SubVotes{types.NewSubVote(types.OptionYes, 1)}, + types.NewNonSplitVoteOption(types.OptionYes), }, { "vote for valid proposal", @@ -732,7 +732,7 @@ func (s *IntegrationTestSuite) TestCmdQueryVote() { fmt.Sprintf("--%s=json", tmcli.OutputFlag), }, false, - types.SubVotes{types.NewSubVote(types.OptionYes, 1)}, + types.NewNonSplitVoteOption(types.OptionYes), }, { "split vote for valid proposal", @@ -742,11 +742,11 @@ func (s *IntegrationTestSuite) TestCmdQueryVote() { fmt.Sprintf("--%s=json", tmcli.OutputFlag), }, false, - types.SubVotes{ - types.SubVote{Option: types.OptionYes, Rate: sdk.NewDecWithPrec(60, 2)}, - types.SubVote{Option: types.OptionNo, Rate: sdk.NewDecWithPrec(30, 2)}, - types.SubVote{Option: types.OptionAbstain, Rate: sdk.NewDecWithPrec(5, 2)}, - types.SubVote{Option: types.OptionNoWithVeto, Rate: sdk.NewDecWithPrec(5, 2)}, + types.WeightedVoteOptions{ + types.WeightedVoteOption{Option: types.OptionYes, Weight: sdk.NewDecWithPrec(60, 2)}, + types.WeightedVoteOption{Option: types.OptionNo, Weight: sdk.NewDecWithPrec(30, 2)}, + types.WeightedVoteOption{Option: types.OptionAbstain, Weight: sdk.NewDecWithPrec(5, 2)}, + types.WeightedVoteOption{Option: types.OptionNoWithVeto, Weight: sdk.NewDecWithPrec(5, 2)}, }, }, } @@ -766,10 +766,10 @@ func (s *IntegrationTestSuite) TestCmdQueryVote() { var vote types.Vote s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &vote), out.String()) - s.Require().Equal(len(vote.SubVotes), len(tc.expSubVotes)) - for i, subvote := range tc.expSubVotes { - s.Require().Equal(subvote.Option, vote.SubVotes[i].Option) - s.Require().True(subvote.Rate.Equal(vote.SubVotes[i].Rate)) + s.Require().Equal(len(vote.Options), len(tc.expVoteOptions)) + for i, option := range tc.expVoteOptions { + s.Require().Equal(option.Option, vote.Options[i].Option) + s.Require().True(option.Weight.Equal(vote.Options[i].Weight)) } } }) diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 35ece9fdc382..374bf24c34b4 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -229,14 +229,14 @@ $ %s tx gov vote 1 yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05 --from mykey return fmt.Errorf("proposal-id %s not a valid int, please input a valid proposal-id", args[0]) } - // Figure out which subvotes user chose - subvotes, err := types.SubVotesFromString(govutils.NormalizeSubVotes(args[1])) + // Figure out which vote options user chose + options, err := types.WeightedVoteOptionsFromString(govutils.NormalizeWeightedVoteOptions(args[1])) if err != nil { return err } // Build vote message and run basic validation - msg := types.NewMsgVote(from, proposalID, subvotes) + msg := types.NewMsgVote(from, proposalID, options) err = msg.ValidateBasic() if err != nil { return err diff --git a/x/gov/client/rest/grpc_query_test.go b/x/gov/client/rest/grpc_query_test.go index 2d7a159c5c2e..cb6918355f57 100644 --- a/x/gov/client/rest/grpc_query_test.go +++ b/x/gov/client/rest/grpc_query_test.go @@ -165,44 +165,44 @@ func (s *IntegrationTestSuite) TestGetProposalVoteGRPC() { voterAddressBase64 := val.Address.String() testCases := []struct { - name string - url string - expErr bool - expSubVotes types.SubVotes + name string + url string + expErr bool + expVoteOptions types.WeightedVoteOptions }{ { "empty proposal", fmt.Sprintf("%s/cosmos/gov/v1beta1/proposals/%s/votes/%s", val.APIAddress, "", voterAddressBase64), true, - types.SubVotes{types.NewSubVote(types.OptionYes, 1)}, + types.NewNonSplitVoteOption(types.OptionYes), }, { "get non existing proposal", fmt.Sprintf("%s/cosmos/gov/v1beta1/proposals/%s/votes/%s", val.APIAddress, "10", voterAddressBase64), true, - types.SubVotes{types.NewSubVote(types.OptionYes, 1)}, + types.NewNonSplitVoteOption(types.OptionYes), }, { "get proposal with wrong voter address", fmt.Sprintf("%s/cosmos/gov/v1beta1/proposals/%s/votes/%s", val.APIAddress, "1", "wrongVoterAddress"), true, - types.SubVotes{types.NewSubVote(types.OptionYes, 1)}, + types.NewNonSplitVoteOption(types.OptionYes), }, { "get proposal with id", fmt.Sprintf("%s/cosmos/gov/v1beta1/proposals/%s/votes/%s", val.APIAddress, "1", voterAddressBase64), false, - types.SubVotes{types.NewSubVote(types.OptionYes, 1)}, + types.NewNonSplitVoteOption(types.OptionYes), }, { "get proposal with id for split vote", fmt.Sprintf("%s/cosmos/gov/v1beta1/proposals/%s/votes/%s", val.APIAddress, "3", voterAddressBase64), false, - types.SubVotes{ - types.SubVote{Option: types.OptionYes, Rate: sdk.NewDecWithPrec(60, 2)}, - types.SubVote{Option: types.OptionNo, Rate: sdk.NewDecWithPrec(30, 2)}, - types.SubVote{Option: types.OptionAbstain, Rate: sdk.NewDecWithPrec(5, 2)}, - types.SubVote{Option: types.OptionNoWithVeto, Rate: sdk.NewDecWithPrec(5, 2)}, + types.WeightedVoteOptions{ + types.WeightedVoteOption{Option: types.OptionYes, Weight: sdk.NewDecWithPrec(60, 2)}, + types.WeightedVoteOption{Option: types.OptionNo, Weight: sdk.NewDecWithPrec(30, 2)}, + types.WeightedVoteOption{Option: types.OptionAbstain, Weight: sdk.NewDecWithPrec(5, 2)}, + types.WeightedVoteOption{Option: types.OptionNoWithVeto, Weight: sdk.NewDecWithPrec(5, 2)}, }, }, } @@ -221,10 +221,10 @@ func (s *IntegrationTestSuite) TestGetProposalVoteGRPC() { } else { s.Require().NoError(err) s.Require().NotEmpty(vote.Vote) - s.Require().Equal(len(vote.Vote.SubVotes), len(tc.expSubVotes)) - for i, subvote := range tc.expSubVotes { - s.Require().Equal(subvote.Option, vote.Vote.SubVotes[i].Option) - s.Require().True(subvote.Rate.Equal(vote.Vote.SubVotes[i].Rate)) + s.Require().Equal(len(vote.Vote.Options), len(tc.expVoteOptions)) + for i, option := range tc.expVoteOptions { + s.Require().Equal(option.Option, vote.Vote.Options[i].Option) + s.Require().True(option.Weight.Equal(vote.Vote.Options[i].Weight)) } } }) diff --git a/x/gov/client/rest/rest.go b/x/gov/client/rest/rest.go index b7375e7e1876..6a52179255f1 100644 --- a/x/gov/client/rest/rest.go +++ b/x/gov/client/rest/rest.go @@ -52,7 +52,7 @@ type DepositReq struct { // VoteReq defines the properties of a vote request's body. type VoteReq struct { - BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` - Voter sdk.AccAddress `json:"voter" yaml:"voter"` // address of the voter - SubVotes string `json:"sub_votes" yaml:"sub_votes"` // option from OptionSet chosen by the voter + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + Voter sdk.AccAddress `json:"voter" yaml:"voter"` // address of the voter + Options string `json:"options" yaml:"options"` // option from OptionSet chosen by the voter } diff --git a/x/gov/client/rest/tx.go b/x/gov/client/rest/tx.go index 3c481660e1e1..00c82dd8cc4d 100644 --- a/x/gov/client/rest/tx.go +++ b/x/gov/client/rest/tx.go @@ -111,14 +111,14 @@ func newVoteHandlerFn(clientCtx client.Context) http.HandlerFunc { return } - // Figure out which subvotes user chose - subvotes, err := types.SubVotesFromString(gcutils.NormalizeSubVotes(req.SubVotes)) + // Figure out which vote options user chose + options, err := types.WeightedVoteOptionsFromString(gcutils.NormalizeWeightedVoteOptions(req.Options)) if err != nil { return } // create the message - msg := types.NewMsgVote(req.Voter, proposalID, subvotes) + msg := types.NewMsgVote(req.Voter, proposalID, options) if rest.CheckBadRequestError(w, msg.ValidateBasic()) { return } diff --git a/x/gov/client/utils/query.go b/x/gov/client/utils/query.go index 44081f8ef6fb..122d7d2557a0 100644 --- a/x/gov/client/utils/query.go +++ b/x/gov/client/utils/query.go @@ -101,7 +101,7 @@ func QueryVotesByTxQuery(clientCtx client.Context, params types.QueryProposalVot votes = append(votes, types.Vote{ Voter: voteMsg.Voter, ProposalId: params.ProposalID, - SubVotes: voteMsg.SubVotes, + Options: voteMsg.Options, }) } } @@ -148,7 +148,7 @@ func QueryVoteByTxQuery(clientCtx client.Context, params types.QueryVoteParams) vote := types.Vote{ Voter: voteMsg.Voter, ProposalId: params.ProposalID, - SubVotes: voteMsg.SubVotes, + Options: voteMsg.Options, } bz, err := clientCtx.JSONMarshaler.MarshalJSON(&vote) diff --git a/x/gov/client/utils/query_test.go b/x/gov/client/utils/query_test.go index 8f792ff1a214..90d3e96c7a8b 100644 --- a/x/gov/client/utils/query_test.go +++ b/x/gov/client/utils/query_test.go @@ -70,12 +70,12 @@ func TestGetPaginatedVotes(t *testing.T) { acc2 := make(sdk.AccAddress, 20) acc2[0] = 2 acc1Msgs := []sdk.Msg{ - types.NewMsgVote(acc1, 0, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), - types.NewMsgVote(acc1, 0, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), + types.NewMsgVote(acc1, 0, types.NewNonSplitVoteOption(types.OptionYes)), + types.NewMsgVote(acc1, 0, types.NewNonSplitVoteOption(types.OptionYes)), } acc2Msgs := []sdk.Msg{ - types.NewMsgVote(acc2, 0, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), - types.NewMsgVote(acc2, 0, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), + types.NewMsgVote(acc2, 0, types.NewNonSplitVoteOption(types.OptionYes)), + types.NewMsgVote(acc2, 0, types.NewNonSplitVoteOption(types.OptionYes)), } for _, tc := range []testCase{ { @@ -87,8 +87,8 @@ func TestGetPaginatedVotes(t *testing.T) { acc2Msgs[:1], }, votes: []types.Vote{ - types.NewVote(0, acc1, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), - types.NewVote(0, acc2, types.SubVotes{types.NewSubVote(types.OptionYes, 1)})}, + types.NewVote(0, acc1, types.NewNonSplitVoteOption(types.OptionYes)), + types.NewVote(0, acc2, types.NewNonSplitVoteOption(types.OptionYes))}, }, { description: "2MsgPerTx1Chunk", @@ -99,8 +99,9 @@ func TestGetPaginatedVotes(t *testing.T) { acc2Msgs, }, votes: []types.Vote{ - types.NewVote(0, acc1, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), - types.NewVote(0, acc1, types.SubVotes{types.NewSubVote(types.OptionYes, 1)})}, + types.NewVote(0, acc1, types.NewNonSplitVoteOption(types.OptionYes)), + types.NewVote(0, acc1, types.NewNonSplitVoteOption(types.OptionYes)), + }, }, { description: "2MsgPerTx2Chunk", @@ -111,8 +112,9 @@ func TestGetPaginatedVotes(t *testing.T) { acc2Msgs, }, votes: []types.Vote{ - types.NewVote(0, acc2, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), - types.NewVote(0, acc2, types.SubVotes{types.NewSubVote(types.OptionYes, 1)})}, + types.NewVote(0, acc2, types.NewNonSplitVoteOption(types.OptionYes)), + types.NewVote(0, acc2, types.NewNonSplitVoteOption(types.OptionYes)), + }, }, { description: "IncompleteSearchTx", @@ -121,7 +123,7 @@ func TestGetPaginatedVotes(t *testing.T) { msgs: [][]sdk.Msg{ acc1Msgs[:1], }, - votes: []types.Vote{types.NewVote(0, acc1, types.SubVotes{types.NewSubVote(types.OptionYes, 1)})}, + votes: []types.Vote{types.NewVote(0, acc1, types.NewNonSplitVoteOption(types.OptionYes))}, }, { description: "InvalidPage", diff --git a/x/gov/client/utils/utils.go b/x/gov/client/utils/utils.go index 9ad73522d070..c45b7980d3ef 100644 --- a/x/gov/client/utils/utils.go +++ b/x/gov/client/utils/utils.go @@ -26,18 +26,18 @@ func NormalizeVoteOption(option string) string { } } -// NormalizeSubVotes - normalize subvotes -func NormalizeSubVotes(subvotes string) string { - newSubVotes := []string{} - for _, subvote := range strings.Split(subvotes, ",") { - fields := strings.Split(subvote, "=") +// NormalizeWeightedVoteOptions - normalize normalize vote options param string +func NormalizeWeightedVoteOptions(options string) string { + newOptions := []string{} + for _, option := range strings.Split(options, ",") { + fields := strings.Split(option, "=") fields[0] = NormalizeVoteOption(fields[0]) if len(fields) < 2 { fields = append(fields, "1") } - newSubVotes = append(newSubVotes, strings.Join(fields, "=")) + newOptions = append(newOptions, strings.Join(fields, "=")) } - return strings.Join(newSubVotes, ",") + return strings.Join(newOptions, ",") } //NormalizeProposalType - normalize user specified proposal type diff --git a/x/gov/keeper/grpc_query_test.go b/x/gov/keeper/grpc_query_test.go index a170c0c0e0b5..4789f954e2dc 100644 --- a/x/gov/keeper/grpc_query_test.go +++ b/x/gov/keeper/grpc_query_test.go @@ -183,7 +183,7 @@ func (suite *KeeperTestSuite) TestGRPCQueryProposals() { func() { testProposals[1].Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, testProposals[1]) - suite.Require().NoError(app.GovKeeper.AddVote(ctx, testProposals[1].ProposalId, addrs[0], types.SubVotes{types.NewSubVote(types.OptionAbstain, 1)})) + suite.Require().NoError(app.GovKeeper.AddVote(ctx, testProposals[1].ProposalId, addrs[0], types.NewNonSplitVoteOption(types.OptionAbstain))) req = &types.QueryProposalsRequest{ Voter: addrs[0].String(), @@ -291,14 +291,14 @@ func (suite *KeeperTestSuite) TestGRPCQueryVote() { func() { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.SubVotes{types.NewSubVote(types.OptionAbstain, 1)})) + suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.NewNonSplitVoteOption(types.OptionAbstain))) req = &types.QueryVoteRequest{ ProposalId: proposal.ProposalId, Voter: addrs[0].String(), } - expRes = &types.QueryVoteResponse{Vote: types.NewVote(proposal.ProposalId, addrs[0], types.SubVotes{types.NewSubVote(types.OptionAbstain, 1)})} + expRes = &types.QueryVoteResponse{Vote: types.NewVote(proposal.ProposalId, addrs[0], types.NewNonSplitVoteOption(types.OptionAbstain))} }, true, }, @@ -395,15 +395,15 @@ func (suite *KeeperTestSuite) TestGRPCQueryVotes() { app.GovKeeper.SetProposal(ctx, proposal) votes = []types.Vote{ - {proposal.ProposalId, addrs[0].String(), types.SubVotes{types.NewSubVote(types.OptionAbstain, 1)}}, - {proposal.ProposalId, addrs[1].String(), types.SubVotes{types.NewSubVote(types.OptionYes, 1)}}, + {proposal.ProposalId, addrs[0].String(), types.NewNonSplitVoteOption(types.OptionAbstain)}, + {proposal.ProposalId, addrs[1].String(), types.NewNonSplitVoteOption(types.OptionYes)}, } accAddr1, err1 := sdk.AccAddressFromBech32(votes[0].Voter) accAddr2, err2 := sdk.AccAddressFromBech32(votes[1].Voter) suite.Require().NoError(err1) suite.Require().NoError(err2) - suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, accAddr1, votes[0].SubVotes)) - suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, accAddr2, votes[1].SubVotes)) + suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, accAddr1, votes[0].Options)) + suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, accAddr2, votes[1].Options)) req = &types.QueryVotesRequest{ ProposalId: proposal.ProposalId, @@ -769,9 +769,9 @@ func (suite *KeeperTestSuite) TestGRPCQueryTally() { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[1], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[2], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.NewNonSplitVoteOption(types.OptionYes))) + suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[1], types.NewNonSplitVoteOption(types.OptionYes))) + suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[2], types.NewNonSplitVoteOption(types.OptionYes))) req = &types.QueryTallyResultRequest{ProposalId: proposal.ProposalId} diff --git a/x/gov/keeper/msg_server.go b/x/gov/keeper/msg_server.go index 2cedfeb23542..aa92591ab9ce 100644 --- a/x/gov/keeper/msg_server.go +++ b/x/gov/keeper/msg_server.go @@ -64,7 +64,7 @@ func (k msgServer) Vote(goCtx context.Context, msg *types.MsgVote) (*types.MsgVo if accErr != nil { return nil, accErr } - err := k.Keeper.AddVote(ctx, msg.ProposalId, accAddr, msg.SubVotes) + err := k.Keeper.AddVote(ctx, msg.ProposalId, accAddr, msg.Options) if err != nil { return nil, err } diff --git a/x/gov/keeper/proposal_test.go b/x/gov/keeper/proposal_test.go index c6c2d803761c..7f62d5a56cc4 100644 --- a/x/gov/keeper/proposal_test.go +++ b/x/gov/keeper/proposal_test.go @@ -101,7 +101,7 @@ func TestGetProposalsFiltered(t *testing.T) { if i%2 == 0 { d := types.NewDeposit(proposalID, addr1, nil) - v := types.NewVote(proposalID, addr1, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}) + v := types.NewVote(proposalID, addr1, types.NewNonSplitVoteOption(types.OptionYes)) app.GovKeeper.SetDeposit(ctx, d) app.GovKeeper.SetVote(ctx, v) } diff --git a/x/gov/keeper/querier_test.go b/x/gov/keeper/querier_test.go index 3e2345b0c7d6..16f2694cd50d 100644 --- a/x/gov/keeper/querier_test.go +++ b/x/gov/keeper/querier_test.go @@ -251,13 +251,13 @@ func TestQueries(t *testing.T) { require.Equal(t, proposal3, proposals[1]) // Addrs[0] votes on proposals #2 & #3 - vote1 := types.NewVote(proposal2.ProposalId, TestAddrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)}) - vote2 := types.NewVote(proposal3.ProposalId, TestAddrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)}) + vote1 := types.NewVote(proposal2.ProposalId, TestAddrs[0], types.NewNonSplitVoteOption(types.OptionYes)) + vote2 := types.NewVote(proposal3.ProposalId, TestAddrs[0], types.NewNonSplitVoteOption(types.OptionYes)) app.GovKeeper.SetVote(ctx, vote1) app.GovKeeper.SetVote(ctx, vote2) // Addrs[1] votes on proposal #3 - vote3 := types.NewVote(proposal3.ProposalId, TestAddrs[1], types.SubVotes{types.NewSubVote(types.OptionYes, 1)}) + vote3 := types.NewVote(proposal3.ProposalId, TestAddrs[1], types.NewNonSplitVoteOption(types.OptionYes)) app.GovKeeper.SetVote(ctx, vote3) // Test query voted by TestAddrs[0] @@ -323,7 +323,7 @@ func TestPaginatedVotesQuery(t *testing.T) { vote := types.Vote{ ProposalId: proposal.ProposalId, Voter: addr.String(), - SubVotes: types.SubVotes{types.NewSubVote(types.OptionYes, 1)}, + Options: types.NewNonSplitVoteOption(types.OptionYes), } votes[i] = vote app.GovKeeper.SetVote(ctx, vote) diff --git a/x/gov/keeper/tally.go b/x/gov/keeper/tally.go index 5e7a9923ffdc..2598293a84ab 100644 --- a/x/gov/keeper/tally.go +++ b/x/gov/keeper/tally.go @@ -27,7 +27,7 @@ func (keeper Keeper) Tally(ctx sdk.Context, proposal types.Proposal) (passes boo validator.GetBondedTokens(), validator.GetDelegatorShares(), sdk.ZeroDec(), - types.SubVotes{}, + types.WeightedVoteOptions{}, ) return false @@ -43,7 +43,7 @@ func (keeper Keeper) Tally(ctx sdk.Context, proposal types.Proposal) (passes boo valAddrStr := sdk.ValAddress(voter.Bytes()).String() if val, ok := currValidators[valAddrStr]; ok { - val.Vote = vote.SubVotes + val.Vote = vote.Options currValidators[valAddrStr] = val } @@ -61,12 +61,12 @@ func (keeper Keeper) Tally(ctx sdk.Context, proposal types.Proposal) (passes boo votingPower := delegatorShare.MulInt(val.BondedTokens) totalRates := sdk.NewDec(0) - for _, subvote := range vote.SubVotes { - totalRates = totalRates.Add(subvote.Rate) + for _, option := range vote.Options { + totalRates = totalRates.Add(option.Weight) } - for _, subvote := range vote.SubVotes { - subPower := sdk.NewDecFromBigInt(votingPower.BigInt().Div(votingPower.Mul(subvote.Rate).BigInt(), totalRates.BigInt())) - results[subvote.Option] = results[subvote.Option].Add(subPower) + for _, option := range vote.Options { + subPower := sdk.NewDecFromBigInt(votingPower.BigInt().Div(votingPower.Mul(option.Weight).BigInt(), totalRates.BigInt())) + results[option.Option] = results[option.Option].Add(subPower) totalVotingPower = totalVotingPower.Add(subPower) } // TODO how should handle remainder? @@ -91,12 +91,12 @@ func (keeper Keeper) Tally(ctx sdk.Context, proposal types.Proposal) (passes boo votingPower := fractionAfterDeductions.MulInt(val.BondedTokens) totalRates := sdk.NewDec(0) - for _, subvote := range val.Vote { - totalRates = totalRates.Add(subvote.Rate) + for _, option := range val.Vote { + totalRates = totalRates.Add(option.Weight) } - for _, subvote := range val.Vote { - subPower := sdk.NewDecFromBigInt(votingPower.BigInt().Div(votingPower.Mul(subvote.Rate).BigInt(), totalRates.BigInt())) - results[subvote.Option] = results[subvote.Option].Add(subPower) + for _, option := range val.Vote { + subPower := sdk.NewDecFromBigInt(votingPower.BigInt().Div(votingPower.Mul(option.Weight).BigInt(), totalRates.BigInt())) + results[option.Option] = results[option.Option].Add(subPower) totalVotingPower = totalVotingPower.Add(subPower) // TODO how should handle remainder? // TODO how should handle when totalRates == 0 diff --git a/x/gov/keeper/tally_test.go b/x/gov/keeper/tally_test.go index 61e07a8a3e96..63ff8e171b1f 100644 --- a/x/gov/keeper/tally_test.go +++ b/x/gov/keeper/tally_test.go @@ -50,7 +50,7 @@ func TestTallyNoQuorum(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - err = app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)}) + err = app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.NewNonSplitVoteOption(types.OptionYes)) require.Nil(t, err) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) @@ -73,9 +73,9 @@ func TestTallyOnlyValidatorsAllYes(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.NewNonSplitVoteOption(types.OptionYes))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.NewNonSplitVoteOption(types.OptionYes))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.NewNonSplitVoteOption(types.OptionYes))) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -99,8 +99,8 @@ func TestTallyOnlyValidators51No(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.NewNonSplitVoteOption(types.OptionYes))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.NewNonSplitVoteOption(types.OptionNo))) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -123,8 +123,8 @@ func TestTallyOnlyValidators51Yes(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.NewNonSplitVoteOption(types.OptionNo))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.NewNonSplitVoteOption(types.OptionYes))) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -148,9 +148,9 @@ func TestTallyOnlyValidatorsVetoed(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[2], types.SubVotes{types.NewSubVote(types.OptionNoWithVeto, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.NewNonSplitVoteOption(types.OptionYes))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.NewNonSplitVoteOption(types.OptionYes))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[2], types.NewNonSplitVoteOption(types.OptionNoWithVeto))) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -174,9 +174,9 @@ func TestTallyOnlyValidatorsAbstainPasses(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.SubVotes{types.NewSubVote(types.OptionAbstain, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[2], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.NewNonSplitVoteOption(types.OptionAbstain))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.NewNonSplitVoteOption(types.OptionNo))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[2], types.NewNonSplitVoteOption(types.OptionYes))) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -200,9 +200,9 @@ func TestTallyOnlyValidatorsAbstainFails(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.SubVotes{types.NewSubVote(types.OptionAbstain, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[2], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[0], types.NewNonSplitVoteOption(types.OptionAbstain))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[1], types.NewNonSplitVoteOption(types.OptionYes))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddrs[2], types.NewNonSplitVoteOption(types.OptionNo))) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -227,8 +227,8 @@ func TestTallyOnlyValidatorsNonVoter(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddr1, types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddr2, types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddr1, types.NewNonSplitVoteOption(types.OptionYes))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, valAccAddr2, types.NewNonSplitVoteOption(types.OptionNo))) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -261,10 +261,10 @@ func TestTallyDelgatorOverride(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[3], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[4], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.NewNonSplitVoteOption(types.OptionYes))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.NewNonSplitVoteOption(types.OptionYes))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[3], types.NewNonSplitVoteOption(types.OptionYes))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[4], types.NewNonSplitVoteOption(types.OptionNo))) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -297,9 +297,9 @@ func TestTallyDelgatorInherit(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.NewNonSplitVoteOption(types.OptionNo))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.NewNonSplitVoteOption(types.OptionNo))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.NewNonSplitVoteOption(types.OptionYes))) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -336,10 +336,10 @@ func TestTallyDelgatorMultipleOverride(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[3], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.NewNonSplitVoteOption(types.OptionYes))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.NewNonSplitVoteOption(types.OptionYes))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.NewNonSplitVoteOption(types.OptionYes))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[3], types.NewNonSplitVoteOption(types.OptionNo))) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -378,9 +378,9 @@ func TestTallyDelgatorMultipleInherit(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.NewNonSplitVoteOption(types.OptionYes))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.NewNonSplitVoteOption(types.OptionNo))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.NewNonSplitVoteOption(types.OptionNo))) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -421,8 +421,8 @@ func TestTallyJailedValidator(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.NewNonSplitVoteOption(types.OptionYes))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.NewNonSplitVoteOption(types.OptionNo))) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) @@ -453,9 +453,9 @@ func TestTallyValidatorMultipleDelegations(t *testing.T) { proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{types.NewSubVote(types.OptionNo, 1)})) - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.NewNonSplitVoteOption(types.OptionYes))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.NewNonSplitVoteOption(types.OptionNo))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.NewNonSplitVoteOption(types.OptionYes))) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) diff --git a/x/gov/keeper/vote.go b/x/gov/keeper/vote.go index 4a298697f519..b554826acd9e 100644 --- a/x/gov/keeper/vote.go +++ b/x/gov/keeper/vote.go @@ -9,7 +9,7 @@ import ( ) // AddVote adds a vote on a specific proposal -func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress, subvotes types.SubVotes) error { +func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress, options types.WeightedVoteOptions) error { proposal, ok := keeper.GetProposal(ctx, proposalID) if !ok { return sdkerrors.Wrapf(types.ErrUnknownProposal, "%d", proposalID) @@ -18,19 +18,19 @@ func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.A return sdkerrors.Wrapf(types.ErrInactiveProposal, "%d", proposalID) } - for _, subvote := range subvotes { - if !types.ValidSubVote(subvote) { - return sdkerrors.Wrap(types.ErrInvalidVote, subvote.String()) + for _, option := range options { + if !types.ValidWeightedVoteOption(option) { + return sdkerrors.Wrap(types.ErrInvalidVote, option.String()) } } - vote := types.NewVote(proposalID, voterAddr, subvotes) + vote := types.NewVote(proposalID, voterAddr, options) keeper.SetVote(ctx, vote) ctx.EventManager().EmitEvent( sdk.NewEvent( types.EventTypeProposalVote, - sdk.NewAttribute(types.AttributeKeyOption, subvotes.String()), + sdk.NewAttribute(types.AttributeKeyOption, options.String()), sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposalID)), ), ) diff --git a/x/gov/keeper/vote_test.go b/x/gov/keeper/vote_test.go index dd7dc34a5739..ae6ebc4a5693 100644 --- a/x/gov/keeper/vote_test.go +++ b/x/gov/keeper/vote_test.go @@ -24,52 +24,52 @@ func TestVotes(t *testing.T) { var invalidOption types.VoteOption = 0x10 - require.Error(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), "proposal not on voting period") - require.Error(t, app.GovKeeper.AddVote(ctx, 10, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)}), "invalid proposal ID") + require.Error(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.NewNonSplitVoteOption(types.OptionYes)), "proposal not on voting period") + require.Error(t, app.GovKeeper.AddVote(ctx, 10, addrs[0], types.NewNonSplitVoteOption(types.OptionYes)), "invalid proposal ID") proposal.Status = types.StatusVotingPeriod app.GovKeeper.SetProposal(ctx, proposal) - require.Error(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(invalidOption, 1)}), "invalid option") + require.Error(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.NewNonSplitVoteOption(invalidOption)), "invalid option") // Test first vote - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionAbstain, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.NewNonSplitVoteOption(types.OptionAbstain))) vote, found := app.GovKeeper.GetVote(ctx, proposalID, addrs[0]) require.True(t, found) require.Equal(t, addrs[0].String(), vote.Voter) require.Equal(t, proposalID, vote.ProposalId) - require.True(t, len(vote.SubVotes) == 1) - require.Equal(t, types.OptionAbstain, vote.SubVotes[0].Option) + require.True(t, len(vote.Options) == 1) + require.Equal(t, types.OptionAbstain, vote.Options[0].Option) // Test change of vote - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.SubVotes{types.NewSubVote(types.OptionYes, 1)})) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.NewNonSplitVoteOption(types.OptionYes))) vote, found = app.GovKeeper.GetVote(ctx, proposalID, addrs[0]) require.True(t, found) require.Equal(t, addrs[0].String(), vote.Voter) require.Equal(t, proposalID, vote.ProposalId) - require.True(t, len(vote.SubVotes) == 1) - require.Equal(t, types.OptionYes, vote.SubVotes[0].Option) + require.True(t, len(vote.Options) == 1) + require.Equal(t, types.OptionYes, vote.Options[0].Option) // Test second vote - require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.SubVotes{ - types.SubVote{Option: types.OptionYes, Rate: sdk.NewDecWithPrec(60, 2)}, - types.SubVote{Option: types.OptionNo, Rate: sdk.NewDecWithPrec(30, 2)}, - types.SubVote{Option: types.OptionAbstain, Rate: sdk.NewDecWithPrec(5, 2)}, - types.SubVote{Option: types.OptionNoWithVeto, Rate: sdk.NewDecWithPrec(5, 2)}, + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.WeightedVoteOptions{ + types.WeightedVoteOption{Option: types.OptionYes, Weight: sdk.NewDecWithPrec(60, 2)}, + types.WeightedVoteOption{Option: types.OptionNo, Weight: sdk.NewDecWithPrec(30, 2)}, + types.WeightedVoteOption{Option: types.OptionAbstain, Weight: sdk.NewDecWithPrec(5, 2)}, + types.WeightedVoteOption{Option: types.OptionNoWithVeto, Weight: sdk.NewDecWithPrec(5, 2)}, })) vote, found = app.GovKeeper.GetVote(ctx, proposalID, addrs[1]) require.True(t, found) require.Equal(t, addrs[1].String(), vote.Voter) require.Equal(t, proposalID, vote.ProposalId) - require.True(t, len(vote.SubVotes) == 4) - require.Equal(t, types.OptionYes, vote.SubVotes[0].Option) - require.Equal(t, types.OptionNo, vote.SubVotes[1].Option) - require.Equal(t, types.OptionAbstain, vote.SubVotes[2].Option) - require.Equal(t, types.OptionNoWithVeto, vote.SubVotes[3].Option) - require.True(t, vote.SubVotes[0].Rate.Equal(sdk.NewDecWithPrec(60, 2))) - require.True(t, vote.SubVotes[1].Rate.Equal(sdk.NewDecWithPrec(30, 2))) - require.True(t, vote.SubVotes[2].Rate.Equal(sdk.NewDecWithPrec(5, 2))) - require.True(t, vote.SubVotes[3].Rate.Equal(sdk.NewDecWithPrec(5, 2))) + require.True(t, len(vote.Options) == 4) + require.Equal(t, types.OptionYes, vote.Options[0].Option) + require.Equal(t, types.OptionNo, vote.Options[1].Option) + require.Equal(t, types.OptionAbstain, vote.Options[2].Option) + require.Equal(t, types.OptionNoWithVeto, vote.Options[3].Option) + require.True(t, vote.Options[0].Weight.Equal(sdk.NewDecWithPrec(60, 2))) + require.True(t, vote.Options[1].Weight.Equal(sdk.NewDecWithPrec(30, 2))) + require.True(t, vote.Options[2].Weight.Equal(sdk.NewDecWithPrec(5, 2))) + require.True(t, vote.Options[3].Weight.Equal(sdk.NewDecWithPrec(5, 2))) // Test vote iterator // NOTE order of deposits is determined by the addresses @@ -78,13 +78,13 @@ func TestVotes(t *testing.T) { require.Equal(t, votes, app.GovKeeper.GetVotes(ctx, proposalID)) require.Equal(t, addrs[0].String(), votes[0].Voter) require.Equal(t, proposalID, votes[0].ProposalId) - require.True(t, len(votes[0].SubVotes) == 1) - require.Equal(t, types.OptionYes, votes[0].SubVotes[0].Option) + require.True(t, len(votes[0].Options) == 1) + require.Equal(t, types.OptionYes, votes[0].Options[0].Option) require.Equal(t, addrs[1].String(), votes[1].Voter) require.Equal(t, proposalID, votes[1].ProposalId) - require.True(t, len(votes[1].SubVotes) == 4) - require.True(t, votes[1].SubVotes[0].Rate.Equal(sdk.NewDecWithPrec(60, 2))) - require.True(t, votes[1].SubVotes[1].Rate.Equal(sdk.NewDecWithPrec(30, 2))) - require.True(t, votes[1].SubVotes[2].Rate.Equal(sdk.NewDecWithPrec(5, 2))) - require.True(t, votes[1].SubVotes[3].Rate.Equal(sdk.NewDecWithPrec(5, 2))) + require.True(t, len(votes[1].Options) == 4) + require.True(t, votes[1].Options[0].Weight.Equal(sdk.NewDecWithPrec(60, 2))) + require.True(t, votes[1].Options[1].Weight.Equal(sdk.NewDecWithPrec(30, 2))) + require.True(t, votes[1].Options[2].Weight.Equal(sdk.NewDecWithPrec(5, 2))) + require.True(t, votes[1].Options[3].Weight.Equal(sdk.NewDecWithPrec(5, 2))) } diff --git a/x/gov/legacy/v040/migrate.go b/x/gov/legacy/v040/migrate.go index bafd933229fc..5cfc76b28136 100644 --- a/x/gov/legacy/v040/migrate.go +++ b/x/gov/legacy/v040/migrate.go @@ -118,7 +118,7 @@ func Migrate(oldGovState v036gov.GenesisState) *v040gov.GenesisState { newVotes[i] = v040gov.Vote{ ProposalId: oldVote.ProposalID, Voter: oldVote.Voter.String(), - SubVotes: v040gov.SubVotes{v040gov.NewSubVote(migrateVoteOption(oldVote.Option), 1)}, + Options: v040gov.NewNonSplitVoteOption(migrateVoteOption(oldVote.Option)), } } diff --git a/x/gov/simulation/decoder_test.go b/x/gov/simulation/decoder_test.go index 4a17cb9a57c6..aac2a4c79184 100644 --- a/x/gov/simulation/decoder_test.go +++ b/x/gov/simulation/decoder_test.go @@ -34,7 +34,7 @@ func TestDecodeStore(t *testing.T) { proposalIDBz := make([]byte, 8) binary.LittleEndian.PutUint64(proposalIDBz, 1) deposit := types.NewDeposit(1, delAddr1, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt()))) - vote := types.NewVote(1, delAddr1, types.SubVotes{types.NewSubVote(types.OptionYes, 1)}) + vote := types.NewVote(1, delAddr1, types.NewNonSplitVoteOption(types.OptionYes)) proposalBz, err := cdc.MarshalBinaryBare(&proposal) require.NoError(t, err) diff --git a/x/gov/simulation/operations.go b/x/gov/simulation/operations.go index c7c7b6aa6261..29196a20c3c6 100644 --- a/x/gov/simulation/operations.go +++ b/x/gov/simulation/operations.go @@ -281,7 +281,7 @@ func operationSimulateMsgVote(ak types.AccountKeeper, bk types.BankKeeper, k kee } option := randomVotingOption(r) - msg := types.NewMsgVote(simAccount.Address, proposalID, types.SubVotes{types.NewSubVote(option, 1)}) + msg := types.NewMsgVote(simAccount.Address, proposalID, types.NewNonSplitVoteOption(option)) account := ak.GetAccount(ctx, simAccount.Address) spendable := bk.SpendableCoins(ctx, account.GetAddress()) diff --git a/x/gov/simulation/operations_test.go b/x/gov/simulation/operations_test.go index 5273de46ac62..83197a585488 100644 --- a/x/gov/simulation/operations_test.go +++ b/x/gov/simulation/operations_test.go @@ -202,8 +202,8 @@ func TestSimulateMsgVote(t *testing.T) { require.True(t, operationMsg.OK) require.Equal(t, uint64(1), msg.ProposalId) require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Voter) - require.True(t, len(msg.SubVotes) == 1) - require.Equal(t, types.OptionYes, msg.SubVotes[0].Option) + require.True(t, len(msg.Options) == 1) + require.Equal(t, types.OptionYes, msg.Options[0].Option) require.Equal(t, "gov", msg.Route()) require.Equal(t, types.TypeMsgVote, msg.Type()) diff --git a/x/gov/types/events.go b/x/gov/types/events.go index 3f3e471cb1a5..19f8857f3a1c 100644 --- a/x/gov/types/events.go +++ b/x/gov/types/events.go @@ -10,7 +10,6 @@ const ( AttributeKeyProposalResult = "proposal_result" AttributeKeyOption = "option" - AttributeKeySubVotes = "sub_votes" AttributeKeyProposalID = "proposal_id" AttributeKeyVotingPeriodStart = "voting_period_start" AttributeValueCategory = "governance" diff --git a/x/gov/types/gov.pb.go b/x/gov/types/gov.pb.go index e6b65c5170c2..f2613c6196dc 100644 --- a/x/gov/types/gov.pb.go +++ b/x/gov/types/gov.pb.go @@ -121,22 +121,23 @@ func (ProposalStatus) EnumDescriptor() ([]byte, []int) { return fileDescriptor_6e82113c1a9a4b7c, []int{1} } -type SubVote struct { +// WeightedVoteOption defines a unit of vote for vote split. +type WeightedVoteOption struct { Option VoteOption `protobuf:"varint,1,opt,name=option,proto3,enum=cosmos.gov.v1beta1.VoteOption" json:"option,omitempty"` - Rate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=rate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"rate" yaml:"rate"` + Weight github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=weight,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"weight" yaml:"weight"` } -func (m *SubVote) Reset() { *m = SubVote{} } -func (*SubVote) ProtoMessage() {} -func (*SubVote) Descriptor() ([]byte, []int) { +func (m *WeightedVoteOption) Reset() { *m = WeightedVoteOption{} } +func (*WeightedVoteOption) ProtoMessage() {} +func (*WeightedVoteOption) Descriptor() ([]byte, []int) { return fileDescriptor_6e82113c1a9a4b7c, []int{0} } -func (m *SubVote) XXX_Unmarshal(b []byte) error { +func (m *WeightedVoteOption) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *SubVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *WeightedVoteOption) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_SubVote.Marshal(b, m, deterministic) + return xxx_messageInfo_WeightedVoteOption.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -146,17 +147,17 @@ func (m *SubVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return b[:n], nil } } -func (m *SubVote) XXX_Merge(src proto.Message) { - xxx_messageInfo_SubVote.Merge(m, src) +func (m *WeightedVoteOption) XXX_Merge(src proto.Message) { + xxx_messageInfo_WeightedVoteOption.Merge(m, src) } -func (m *SubVote) XXX_Size() int { +func (m *WeightedVoteOption) XXX_Size() int { return m.Size() } -func (m *SubVote) XXX_DiscardUnknown() { - xxx_messageInfo_SubVote.DiscardUnknown(m) +func (m *WeightedVoteOption) XXX_DiscardUnknown() { + xxx_messageInfo_WeightedVoteOption.DiscardUnknown(m) } -var xxx_messageInfo_SubVote proto.InternalMessageInfo +var xxx_messageInfo_WeightedVoteOption proto.InternalMessageInfo // TextProposal defines a standard text proposal whose changes need to be // manually updated in case of approval. @@ -325,9 +326,9 @@ var xxx_messageInfo_TallyResult proto.InternalMessageInfo // Vote defines a vote on a governance proposal. // A Vote consists of a proposal ID, the voter, and the vote option. type Vote struct { - ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty" yaml:"proposal_id"` - Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` - SubVotes []SubVote `protobuf:"bytes,3,rep,name=sub_votes,json=subVotes,proto3" json:"sub_votes"` + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty" yaml:"proposal_id"` + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` + Options []WeightedVoteOption `protobuf:"bytes,3,rep,name=options,proto3" json:"options"` } func (m *Vote) Reset() { *m = Vote{} } @@ -488,7 +489,7 @@ var xxx_messageInfo_TallyParams proto.InternalMessageInfo func init() { proto.RegisterEnum("cosmos.gov.v1beta1.VoteOption", VoteOption_name, VoteOption_value) proto.RegisterEnum("cosmos.gov.v1beta1.ProposalStatus", ProposalStatus_name, ProposalStatus_value) - proto.RegisterType((*SubVote)(nil), "cosmos.gov.v1beta1.SubVote") + proto.RegisterType((*WeightedVoteOption)(nil), "cosmos.gov.v1beta1.WeightedVoteOption") proto.RegisterType((*TextProposal)(nil), "cosmos.gov.v1beta1.TextProposal") proto.RegisterType((*Deposit)(nil), "cosmos.gov.v1beta1.Deposit") proto.RegisterType((*Proposal)(nil), "cosmos.gov.v1beta1.Proposal") @@ -502,98 +503,97 @@ func init() { func init() { proto.RegisterFile("cosmos/gov/v1beta1/gov.proto", fileDescriptor_6e82113c1a9a4b7c) } var fileDescriptor_6e82113c1a9a4b7c = []byte{ - // 1442 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0x5f, 0x6c, 0xdb, 0x54, - 0x17, 0x8f, 0xd3, 0xf4, 0x4f, 0x6e, 0xd2, 0xd6, 0xbb, 0xed, 0xda, 0x34, 0xdb, 0x67, 0xfb, 0xf3, - 0xf7, 0x09, 0x55, 0xd3, 0x96, 0x6e, 0x05, 0x81, 0xe8, 0xc4, 0x44, 0xdc, 0x78, 0x2c, 0x68, 0x4a, - 0x82, 0xe3, 0x65, 0xda, 0x78, 0xb0, 0x9c, 0xe4, 0x2e, 0x35, 0xc4, 0xbe, 0x21, 0xbe, 0x29, 0xad, - 0x78, 0xe1, 0x71, 0x0a, 0x12, 0xda, 0x03, 0x0f, 0x93, 0x50, 0xc4, 0x24, 0xde, 0x78, 0xe6, 0x99, - 0xe7, 0x0a, 0x21, 0x31, 0xf1, 0x34, 0x81, 0x94, 0xb1, 0x4e, 0x42, 0x53, 0x1f, 0xfb, 0xc0, 0x33, - 0xb2, 0xef, 0x75, 0xe3, 0x24, 0x15, 0x25, 0x3c, 0xd5, 0xf7, 0xdc, 0xf3, 0xfb, 0xfd, 0xce, 0x39, - 0x3e, 0xe7, 0xc4, 0x05, 0x17, 0x6b, 0xd8, 0xb5, 0xb1, 0xbb, 0xd1, 0xc0, 0xbb, 0x1b, 0xbb, 0xd7, - 0xaa, 0x88, 0x98, 0xd7, 0xbc, 0xe7, 0x4c, 0xab, 0x8d, 0x09, 0x86, 0x90, 0xde, 0x66, 0x3c, 0x0b, - 0xbb, 0x4d, 0x0b, 0x0c, 0x51, 0x35, 0x5d, 0x74, 0x02, 0xa9, 0x61, 0xcb, 0xa1, 0x98, 0xf4, 0x72, - 0x03, 0x37, 0xb0, 0xff, 0xb8, 0xe1, 0x3d, 0x31, 0xeb, 0x1a, 0x45, 0x19, 0xf4, 0x82, 0xd1, 0xd2, - 0x2b, 0xb1, 0x81, 0x71, 0xa3, 0x89, 0x36, 0xfc, 0x53, 0xb5, 0xf3, 0x60, 0x83, 0x58, 0x36, 0x72, - 0x89, 0x69, 0xb7, 0x02, 0xec, 0xa8, 0x83, 0xe9, 0xec, 0xb3, 0x2b, 0x61, 0xf4, 0xaa, 0xde, 0x69, - 0x9b, 0xc4, 0xc2, 0x2c, 0x18, 0xf9, 0x2b, 0x0e, 0xcc, 0x96, 0x3b, 0xd5, 0x0a, 0x26, 0x08, 0xbe, - 0x09, 0x66, 0x70, 0xcb, 0xbb, 0x4b, 0x71, 0x12, 0xb7, 0xbe, 0xb0, 0x29, 0x64, 0xc6, 0xb3, 0xcb, - 0x78, 0x9e, 0x45, 0xdf, 0x4b, 0x63, 0xde, 0xf0, 0x03, 0x10, 0x6b, 0x9b, 0x04, 0xa5, 0xa2, 0x12, - 0xb7, 0x1e, 0x57, 0xde, 0x39, 0xe8, 0x8b, 0x91, 0x5f, 0xfb, 0xe2, 0x6b, 0x0d, 0x8b, 0xec, 0x74, - 0xaa, 0x99, 0x1a, 0xb6, 0x59, 0x3a, 0xec, 0xcf, 0x15, 0xb7, 0xfe, 0xf1, 0x06, 0xd9, 0x6f, 0x21, - 0x37, 0x93, 0x43, 0xb5, 0xe3, 0xbe, 0x98, 0xd8, 0x37, 0xed, 0xe6, 0x96, 0xec, 0x71, 0xc8, 0x9a, - 0x4f, 0x25, 0xdf, 0x05, 0x49, 0x1d, 0xed, 0x91, 0x52, 0x1b, 0xb7, 0xb0, 0x6b, 0x36, 0xe1, 0x32, - 0x98, 0x26, 0x16, 0x69, 0x22, 0x3f, 0xb2, 0xb8, 0x46, 0x0f, 0x50, 0x02, 0x89, 0x3a, 0x72, 0x6b, - 0x6d, 0x8b, 0x46, 0xed, 0xeb, 0x6b, 0x61, 0xd3, 0xd6, 0xe2, 0xab, 0x27, 0x22, 0xf7, 0xcb, 0xf7, - 0x57, 0x66, 0xb7, 0xb1, 0x43, 0x90, 0x43, 0xe4, 0x9f, 0x39, 0x30, 0x9b, 0x43, 0x2d, 0xec, 0x5a, - 0x04, 0xbe, 0x05, 0x12, 0x2d, 0x26, 0x60, 0x58, 0x75, 0x9f, 0x3a, 0xa6, 0xac, 0x1c, 0xf7, 0x45, - 0x48, 0x03, 0x0a, 0x5d, 0xca, 0x1a, 0x08, 0x4e, 0xf9, 0x3a, 0xbc, 0x08, 0xe2, 0x75, 0xca, 0x81, - 0xdb, 0x4c, 0x75, 0x60, 0x80, 0x35, 0x30, 0x63, 0xda, 0xb8, 0xe3, 0x90, 0xd4, 0x94, 0x34, 0xb5, - 0x9e, 0xd8, 0x5c, 0x0b, 0xca, 0xe8, 0x35, 0xc4, 0x49, 0x1d, 0xb7, 0xb1, 0xe5, 0x28, 0x57, 0xbd, - 0x5a, 0x7d, 0xf7, 0x5c, 0x5c, 0xff, 0x07, 0xb5, 0xf2, 0x00, 0xae, 0xc6, 0xa8, 0xb7, 0xe6, 0x1e, - 0x3e, 0x11, 0x23, 0xaf, 0x9e, 0x88, 0x11, 0xf9, 0xcf, 0x19, 0x30, 0x77, 0x52, 0xa7, 0x37, 0x4e, - 0x4b, 0x69, 0xe9, 0xa8, 0x2f, 0x46, 0xad, 0xfa, 0x71, 0x5f, 0x8c, 0xd3, 0xc4, 0x46, 0xf3, 0xb9, - 0x0e, 0x66, 0x6b, 0xb4, 0x3e, 0x7e, 0x36, 0x89, 0xcd, 0xe5, 0x0c, 0x6d, 0x9b, 0x4c, 0xd0, 0x36, - 0x99, 0xac, 0xb3, 0xaf, 0x24, 0x7e, 0x1c, 0x14, 0x52, 0x0b, 0x10, 0xb0, 0x02, 0x66, 0x5c, 0x62, - 0x92, 0x8e, 0x9b, 0x9a, 0xf2, 0xbb, 0x46, 0x3e, 0xad, 0x6b, 0x82, 0x00, 0xcb, 0xbe, 0xa7, 0x92, - 0x3e, 0xee, 0x8b, 0x2b, 0x23, 0x45, 0xa6, 0x24, 0xb2, 0xc6, 0xd8, 0x60, 0x0b, 0xc0, 0x07, 0x96, - 0x63, 0x36, 0x0d, 0x62, 0x36, 0x9b, 0xfb, 0x46, 0x1b, 0xb9, 0x9d, 0x26, 0x49, 0xc5, 0xfc, 0xf8, - 0xc4, 0xd3, 0x34, 0x74, 0xcf, 0x4f, 0xf3, 0xdd, 0x94, 0xff, 0x7a, 0x85, 0x3d, 0xee, 0x8b, 0x6b, - 0x54, 0x64, 0x9c, 0x48, 0xd6, 0x78, 0xdf, 0x18, 0x02, 0xc1, 0x0f, 0x41, 0xc2, 0xed, 0x54, 0x6d, - 0x8b, 0x18, 0xde, 0x80, 0xa5, 0xa6, 0x7d, 0xa9, 0xf4, 0x58, 0x29, 0xf4, 0x60, 0xfa, 0x14, 0x81, - 0xa9, 0xb0, 0x7e, 0x09, 0x81, 0xe5, 0x47, 0xcf, 0x45, 0x4e, 0x03, 0xd4, 0xe2, 0x01, 0xa0, 0x05, - 0x78, 0xd6, 0x22, 0x06, 0x72, 0xea, 0x54, 0x61, 0xe6, 0x4c, 0x85, 0xff, 0x31, 0x85, 0x55, 0xaa, - 0x30, 0xca, 0x40, 0x65, 0x16, 0x98, 0x59, 0x75, 0xea, 0xbe, 0xd4, 0x43, 0x0e, 0xcc, 0x13, 0x4c, - 0xcc, 0xa6, 0xc1, 0x2e, 0x52, 0xb3, 0x67, 0x35, 0xe2, 0x2d, 0xa6, 0xb3, 0x4c, 0x75, 0x86, 0xd0, - 0xf2, 0x44, 0x0d, 0x9a, 0xf4, 0xb1, 0xc1, 0x88, 0x35, 0xc1, 0xb9, 0x5d, 0x4c, 0x2c, 0xa7, 0xe1, - 0xbd, 0xde, 0x36, 0x2b, 0xec, 0xdc, 0x99, 0x69, 0xff, 0x9f, 0x85, 0x93, 0xa2, 0xe1, 0x8c, 0x51, - 0xd0, 0xbc, 0x17, 0xa9, 0xbd, 0xec, 0x99, 0xfd, 0xc4, 0x1f, 0x00, 0x66, 0x1a, 0x94, 0x38, 0x7e, - 0xa6, 0x96, 0xcc, 0xb4, 0x56, 0x86, 0xb4, 0x86, 0x2b, 0x3c, 0x4f, 0xad, 0xac, 0xc0, 0x5b, 0x31, - 0x6f, 0xab, 0xc8, 0x07, 0x51, 0x90, 0x08, 0xb7, 0xcf, 0xbb, 0x60, 0x6a, 0x1f, 0xb9, 0x74, 0x43, - 0x29, 0x99, 0x09, 0xb6, 0x60, 0xde, 0x21, 0x9a, 0x07, 0x85, 0xb7, 0xc0, 0xac, 0x59, 0x75, 0x89, - 0x69, 0xb1, 0x5d, 0x36, 0x31, 0x4b, 0x00, 0x87, 0x37, 0x40, 0xd4, 0xc1, 0xfe, 0x40, 0x4e, 0x4e, - 0x12, 0x75, 0x30, 0x6c, 0x80, 0xa4, 0x83, 0x8d, 0x4f, 0x2d, 0xb2, 0x63, 0xec, 0x22, 0x82, 0xfd, - 0xb1, 0x8b, 0x2b, 0xea, 0x64, 0x4c, 0xc7, 0x7d, 0x71, 0x89, 0x16, 0x35, 0xcc, 0x25, 0x6b, 0xc0, - 0xc1, 0x77, 0x2d, 0xb2, 0x53, 0x41, 0x04, 0xb3, 0x52, 0x7e, 0xc3, 0x81, 0x98, 0xff, 0x13, 0xf4, - 0xaf, 0x57, 0xf2, 0x32, 0x98, 0xde, 0xc5, 0x04, 0x05, 0xeb, 0x98, 0x1e, 0xe0, 0x0d, 0x10, 0x77, - 0x3b, 0x55, 0xc3, 0x3b, 0xb8, 0x6c, 0x1b, 0x5f, 0x38, 0x6d, 0x75, 0xb0, 0x5f, 0x40, 0x25, 0xe6, - 0x25, 0xa8, 0xcd, 0xb9, 0xf4, 0xe8, 0x6e, 0xcd, 0x3d, 0x0e, 0xb6, 0xec, 0x0f, 0x51, 0x30, 0xcf, - 0x9a, 0xba, 0x64, 0xb6, 0x4d, 0xdb, 0x85, 0x5f, 0x73, 0x20, 0x61, 0x5b, 0xce, 0xc9, 0x8c, 0x71, - 0x67, 0xcd, 0x98, 0xe1, 0x91, 0x1f, 0xf5, 0xc5, 0xf3, 0x21, 0xd4, 0x65, 0x6c, 0x5b, 0x04, 0xd9, - 0x2d, 0xb2, 0x3f, 0xc8, 0x31, 0x74, 0x3d, 0xd9, 0xe8, 0x01, 0xdb, 0x72, 0x82, 0xc1, 0xfb, 0x92, - 0x03, 0xd0, 0x36, 0xf7, 0x02, 0x22, 0xa3, 0x85, 0xda, 0x16, 0xae, 0xb3, 0xf5, 0xbe, 0x36, 0x36, - 0x0e, 0x39, 0xf6, 0x55, 0x40, 0x5f, 0xf1, 0x51, 0x5f, 0xbc, 0x38, 0x0e, 0x1e, 0x8a, 0x95, 0x2d, - 0xd6, 0x71, 0x2f, 0xf9, 0xb1, 0x37, 0x30, 0xbc, 0x6d, 0xee, 0x05, 0xe5, 0xa2, 0xe6, 0x2f, 0x38, - 0x90, 0xac, 0xf8, 0x53, 0xc4, 0xea, 0xf7, 0x19, 0x60, 0x53, 0x15, 0xc4, 0xc6, 0x9d, 0x15, 0xdb, - 0x75, 0x16, 0xdb, 0xea, 0x10, 0x6e, 0x28, 0xac, 0xe5, 0xa1, 0x21, 0x0e, 0x47, 0x94, 0xa4, 0x36, - 0x16, 0xcd, 0x6f, 0xc1, 0xec, 0xb2, 0x60, 0xee, 0x83, 0x99, 0x4f, 0x3a, 0xb8, 0xdd, 0xb1, 0xfd, - 0x28, 0x92, 0x8a, 0x32, 0xd9, 0x47, 0xcc, 0x51, 0x5f, 0xe4, 0x29, 0x7e, 0x10, 0x8d, 0xc6, 0x18, - 0x61, 0x0d, 0xc4, 0xc9, 0x4e, 0x1b, 0xb9, 0x3b, 0xb8, 0x49, 0x5f, 0x40, 0x72, 0xa2, 0x41, 0xa2, - 0xf4, 0x4b, 0x27, 0x14, 0x21, 0x85, 0x01, 0x2f, 0xec, 0x72, 0x60, 0xc1, 0x9b, 0x2e, 0x63, 0x20, - 0x35, 0xe5, 0x4b, 0xd5, 0x26, 0x96, 0x4a, 0x0d, 0xf3, 0x0c, 0xd5, 0xf7, 0x3c, 0xab, 0xef, 0x90, - 0x87, 0xac, 0xcd, 0x7b, 0x06, 0x3d, 0x38, 0x5f, 0xfa, 0x83, 0x03, 0x60, 0xf0, 0x9d, 0x08, 0x2f, - 0x83, 0xd5, 0x4a, 0x51, 0x57, 0x8d, 0x62, 0x49, 0xcf, 0x17, 0x0b, 0xc6, 0x9d, 0x42, 0xb9, 0xa4, - 0x6e, 0xe7, 0x6f, 0xe6, 0xd5, 0x1c, 0x1f, 0x49, 0x2f, 0x76, 0x7b, 0x52, 0x82, 0x3a, 0xaa, 0x9e, - 0x08, 0x94, 0xc1, 0x62, 0xd8, 0xfb, 0x9e, 0x5a, 0xe6, 0xb9, 0xf4, 0x7c, 0xb7, 0x27, 0xc5, 0xa9, - 0xd7, 0x3d, 0xe4, 0xc2, 0x4b, 0x60, 0x29, 0xec, 0x93, 0x55, 0xca, 0x7a, 0x36, 0x5f, 0xe0, 0xa3, - 0xe9, 0x73, 0xdd, 0x9e, 0x34, 0x4f, 0xfd, 0xb2, 0x6c, 0x15, 0x4a, 0x60, 0x21, 0xec, 0x5b, 0x28, - 0xf2, 0x53, 0xe9, 0x64, 0xb7, 0x27, 0xcd, 0x51, 0xb7, 0x02, 0x86, 0x9b, 0x20, 0x35, 0xec, 0x61, - 0xdc, 0xcd, 0xeb, 0xb7, 0x8c, 0x8a, 0xaa, 0x17, 0xf9, 0x58, 0x7a, 0xb9, 0xdb, 0x93, 0xf8, 0xc0, - 0x37, 0xd8, 0x5b, 0xe9, 0xd8, 0xc3, 0x6f, 0x85, 0xc8, 0xa5, 0x9f, 0xa2, 0x60, 0x61, 0xf8, 0xd3, - 0x06, 0x66, 0xc0, 0x85, 0x92, 0x56, 0x2c, 0x15, 0xcb, 0xd9, 0xdb, 0x46, 0x59, 0xcf, 0xea, 0x77, - 0xca, 0x23, 0x09, 0xfb, 0xa9, 0x50, 0xe7, 0x82, 0xd5, 0x84, 0xd7, 0x81, 0x30, 0xea, 0x9f, 0x53, - 0x4b, 0xc5, 0x72, 0x5e, 0x37, 0x4a, 0xaa, 0x96, 0x2f, 0xe6, 0x78, 0x2e, 0xbd, 0xda, 0xed, 0x49, - 0x4b, 0x14, 0x32, 0x34, 0x54, 0xf0, 0x6d, 0xf0, 0x9f, 0x51, 0x70, 0xa5, 0xa8, 0xe7, 0x0b, 0xef, - 0x05, 0xd8, 0x68, 0x7a, 0xa5, 0xdb, 0x93, 0x20, 0xc5, 0x56, 0x42, 0x13, 0x00, 0x2f, 0x83, 0x95, - 0x51, 0x68, 0x29, 0x5b, 0x2e, 0xab, 0x39, 0x7e, 0x2a, 0xcd, 0x77, 0x7b, 0x52, 0x92, 0x62, 0x4a, - 0xa6, 0xeb, 0xa2, 0x3a, 0xbc, 0x0a, 0x52, 0xa3, 0xde, 0x9a, 0xfa, 0xbe, 0xba, 0xad, 0xab, 0x39, - 0x3e, 0x96, 0x86, 0xdd, 0x9e, 0xb4, 0x40, 0xfd, 0x35, 0xf4, 0x11, 0xaa, 0x11, 0x74, 0x2a, 0xff, - 0xcd, 0x6c, 0xfe, 0xb6, 0x9a, 0xe3, 0xa7, 0xc3, 0xfc, 0x37, 0x4d, 0xab, 0x89, 0xea, 0xb4, 0x9c, - 0x4a, 0xe1, 0xe0, 0x85, 0x10, 0x79, 0xf6, 0x42, 0x88, 0x7c, 0x7e, 0x28, 0x44, 0x0e, 0x0e, 0x05, - 0xee, 0xe9, 0xa1, 0xc0, 0xfd, 0x7e, 0x28, 0x70, 0x8f, 0x5e, 0x0a, 0x91, 0xa7, 0x2f, 0x85, 0xc8, - 0xb3, 0x97, 0x42, 0xe4, 0xfe, 0xdf, 0x2f, 0xc4, 0x3d, 0xff, 0x3f, 0x35, 0xbf, 0x9f, 0xab, 0x33, - 0xfe, 0x0e, 0x79, 0xfd, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd7, 0x68, 0xea, 0xf2, 0xc4, 0x0d, - 0x00, 0x00, + // 1438 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0x51, 0x68, 0xdb, 0x56, + 0x17, 0xb6, 0x1c, 0xc7, 0x89, 0xaf, 0x9d, 0x44, 0xbd, 0x49, 0x13, 0xc7, 0x7f, 0x7f, 0xc9, 0xd3, + 0x46, 0x09, 0xa5, 0x75, 0xda, 0x6c, 0x6c, 0x2c, 0x85, 0x6d, 0x56, 0xac, 0xac, 0x1e, 0xc5, 0x36, + 0xb2, 0xea, 0xd0, 0xee, 0x41, 0x28, 0xf6, 0xad, 0xa3, 0xcd, 0xd2, 0xf5, 0xac, 0xeb, 0x34, 0x66, + 0x2f, 0x7b, 0x2c, 0x1e, 0x8c, 0x3e, 0x16, 0x86, 0xa1, 0x30, 0xc6, 0x60, 0xcf, 0x7b, 0xde, 0x73, + 0x18, 0x83, 0x95, 0x3d, 0x95, 0x0d, 0xdc, 0x35, 0x85, 0x51, 0xf2, 0x98, 0x87, 0x3d, 0x0f, 0xe9, + 0x5e, 0xc5, 0xb2, 0x1d, 0x96, 0x79, 0x4f, 0xd1, 0x3d, 0xf7, 0x7c, 0xdf, 0x77, 0xce, 0xf1, 0x39, + 0x47, 0x0a, 0xb8, 0x54, 0xc5, 0x8e, 0x85, 0x9d, 0xf5, 0x3a, 0xde, 0x5f, 0xdf, 0xbf, 0xb1, 0x8b, + 0x88, 0x71, 0xc3, 0x7d, 0xce, 0x34, 0x5b, 0x98, 0x60, 0x08, 0xe9, 0x6d, 0xc6, 0xb5, 0xb0, 0xdb, + 0x94, 0xc0, 0x10, 0xbb, 0x86, 0x83, 0x4e, 0x21, 0x55, 0x6c, 0xda, 0x14, 0x93, 0x5a, 0xaa, 0xe3, + 0x3a, 0xf6, 0x1e, 0xd7, 0xdd, 0x27, 0x66, 0x5d, 0xa5, 0x28, 0x9d, 0x5e, 0x30, 0x5a, 0x7a, 0x25, + 0xd6, 0x31, 0xae, 0x37, 0xd0, 0xba, 0x77, 0xda, 0x6d, 0xdf, 0x5f, 0x27, 0xa6, 0x85, 0x1c, 0x62, + 0x58, 0x4d, 0x1f, 0x3b, 0xea, 0x60, 0xd8, 0x1d, 0x76, 0x25, 0x8c, 0x5e, 0xd5, 0xda, 0x2d, 0x83, + 0x98, 0x98, 0x05, 0x23, 0x7d, 0xcb, 0x01, 0xb8, 0x83, 0xcc, 0xfa, 0x1e, 0x41, 0xb5, 0x0a, 0x26, + 0xa8, 0xd8, 0x74, 0x2f, 0xe1, 0xdb, 0x20, 0x8a, 0xbd, 0xa7, 0x24, 0x97, 0xe6, 0xd6, 0xe6, 0x37, + 0x84, 0xcc, 0x78, 0xa2, 0x99, 0x81, 0xbf, 0xca, 0xbc, 0xe1, 0x0e, 0x88, 0x3e, 0xf0, 0xd8, 0x92, + 0xe1, 0x34, 0xb7, 0x16, 0x93, 0xdf, 0x3f, 0xec, 0x8b, 0xa1, 0xdf, 0xfa, 0xe2, 0xe5, 0xba, 0x49, + 0xf6, 0xda, 0xbb, 0x99, 0x2a, 0xb6, 0x58, 0x6e, 0xec, 0xcf, 0x35, 0xa7, 0xf6, 0xe9, 0x3a, 0xe9, + 0x34, 0x91, 0x93, 0xc9, 0xa1, 0xea, 0x49, 0x5f, 0x9c, 0xeb, 0x18, 0x56, 0x63, 0x53, 0xa2, 0x2c, + 0x92, 0xca, 0xe8, 0xa4, 0x1d, 0x90, 0xd0, 0xd0, 0x01, 0x29, 0xb5, 0x70, 0x13, 0x3b, 0x46, 0x03, + 0x2e, 0x81, 0x69, 0x62, 0x92, 0x06, 0xf2, 0xe2, 0x8b, 0xa9, 0xf4, 0x00, 0xd3, 0x20, 0x5e, 0x43, + 0x4e, 0xb5, 0x65, 0xd2, 0xd8, 0xbd, 0x18, 0xd4, 0xa0, 0x69, 0x73, 0xe1, 0xd5, 0x13, 0x91, 0xfb, + 0xf5, 0x87, 0x6b, 0x33, 0x5b, 0xd8, 0x26, 0xc8, 0x26, 0xd2, 0x2f, 0x1c, 0x98, 0xc9, 0xa1, 0x26, + 0x76, 0x4c, 0x02, 0xdf, 0x01, 0xf1, 0x26, 0x13, 0xd0, 0xcd, 0x9a, 0x47, 0x1d, 0x91, 0x97, 0x4f, + 0xfa, 0x22, 0xa4, 0x41, 0x05, 0x2e, 0x25, 0x15, 0xf8, 0xa7, 0x7c, 0x0d, 0x5e, 0x02, 0xb1, 0x1a, + 0xe5, 0xc0, 0x2d, 0xa6, 0x3a, 0x30, 0xc0, 0x2a, 0x88, 0x1a, 0x16, 0x6e, 0xdb, 0x24, 0x39, 0x95, + 0x9e, 0x5a, 0x8b, 0x6f, 0xac, 0xfa, 0xc5, 0x74, 0x3b, 0xe4, 0xb4, 0x9a, 0x5b, 0xd8, 0xb4, 0xe5, + 0xeb, 0x6e, 0xbd, 0xbe, 0x7f, 0x2e, 0xae, 0xfd, 0x8b, 0x7a, 0xb9, 0x00, 0x47, 0x65, 0xd4, 0x9b, + 0xb3, 0x0f, 0x9f, 0x88, 0xa1, 0x57, 0x4f, 0xc4, 0x90, 0xf4, 0x57, 0x14, 0xcc, 0x9e, 0xd6, 0xe9, + 0xad, 0xb3, 0x52, 0x5a, 0x3c, 0xee, 0x8b, 0x61, 0xb3, 0x76, 0xd2, 0x17, 0x63, 0x34, 0xb1, 0xd1, + 0x7c, 0x6e, 0x82, 0x99, 0x2a, 0xad, 0x8f, 0x97, 0x4d, 0x7c, 0x63, 0x29, 0x43, 0xfb, 0x28, 0xe3, + 0xf7, 0x51, 0x26, 0x6b, 0x77, 0xe4, 0xf8, 0x4f, 0x83, 0x42, 0xaa, 0x3e, 0x02, 0x56, 0x40, 0xd4, + 0x21, 0x06, 0x69, 0x3b, 0xc9, 0x29, 0xaf, 0x77, 0xa4, 0xb3, 0x7a, 0xc7, 0x0f, 0xb0, 0xec, 0x79, + 0xca, 0xa9, 0x93, 0xbe, 0xb8, 0x3c, 0x52, 0x64, 0x4a, 0x22, 0xa9, 0x8c, 0x0d, 0x36, 0x01, 0xbc, + 0x6f, 0xda, 0x46, 0x43, 0x27, 0x46, 0xa3, 0xd1, 0xd1, 0x5b, 0xc8, 0x69, 0x37, 0x48, 0x32, 0xe2, + 0xc5, 0x27, 0x9e, 0xa5, 0xa1, 0xb9, 0x7e, 0xaa, 0xe7, 0x26, 0xbf, 0xe6, 0x16, 0xf6, 0xa4, 0x2f, + 0xae, 0x52, 0x91, 0x71, 0x22, 0x49, 0xe5, 0x3d, 0x63, 0x00, 0x04, 0x3f, 0x06, 0x71, 0xa7, 0xbd, + 0x6b, 0x99, 0x44, 0x77, 0x27, 0x2e, 0x39, 0xed, 0x49, 0xa5, 0xc6, 0x4a, 0xa1, 0xf9, 0xe3, 0x28, + 0x0b, 0x4c, 0x85, 0xf5, 0x4b, 0x00, 0x2c, 0x3d, 0x7a, 0x2e, 0x72, 0x2a, 0xa0, 0x16, 0x17, 0x00, + 0x4d, 0xc0, 0xb3, 0x16, 0xd1, 0x91, 0x5d, 0xa3, 0x0a, 0xd1, 0x73, 0x15, 0x5e, 0x67, 0x0a, 0x2b, + 0x54, 0x61, 0x94, 0x81, 0xca, 0xcc, 0x33, 0xb3, 0x62, 0xd7, 0x3c, 0xa9, 0x87, 0x1c, 0x98, 0x23, + 0x98, 0x18, 0x0d, 0x9d, 0x5d, 0x24, 0x67, 0xce, 0x6b, 0xc4, 0x5b, 0x4c, 0x67, 0x89, 0xea, 0x0c, + 0xa1, 0xa5, 0x89, 0x1a, 0x34, 0xe1, 0x61, 0xfd, 0x11, 0x6b, 0x80, 0x0b, 0xfb, 0x98, 0x98, 0x76, + 0xdd, 0xfd, 0x79, 0x5b, 0xac, 0xb0, 0xb3, 0xe7, 0xa6, 0xfd, 0x06, 0x0b, 0x27, 0x49, 0xc3, 0x19, + 0xa3, 0xa0, 0x79, 0x2f, 0x50, 0x7b, 0xd9, 0x35, 0x7b, 0x89, 0xdf, 0x07, 0xcc, 0x34, 0x28, 0x71, + 0xec, 0x5c, 0x2d, 0x89, 0x69, 0x2d, 0x0f, 0x69, 0x0d, 0x57, 0x78, 0x8e, 0x5a, 0x59, 0x81, 0x37, + 0x23, 0xee, 0x56, 0x91, 0x0e, 0xc3, 0x20, 0x1e, 0x6c, 0x9f, 0x0f, 0xc0, 0x54, 0x07, 0x39, 0x74, + 0x43, 0xc9, 0x99, 0x09, 0x36, 0x61, 0xde, 0x26, 0xaa, 0x0b, 0x85, 0xb7, 0xc0, 0x8c, 0xb1, 0xeb, + 0x10, 0xc3, 0x64, 0xbb, 0x6c, 0x62, 0x16, 0x1f, 0x0e, 0xdf, 0x03, 0x61, 0x1b, 0x7b, 0x03, 0x39, + 0x39, 0x49, 0xd8, 0xc6, 0xb0, 0x0e, 0x12, 0x36, 0xd6, 0x1f, 0x98, 0x64, 0x4f, 0xdf, 0x47, 0x04, + 0x7b, 0x63, 0x17, 0x93, 0x95, 0xc9, 0x98, 0x4e, 0xfa, 0xe2, 0x22, 0x2d, 0x6a, 0x90, 0x4b, 0x52, + 0x81, 0x8d, 0x77, 0x4c, 0xb2, 0x57, 0x41, 0x04, 0xb3, 0x52, 0x7e, 0xc7, 0x81, 0x88, 0xfb, 0x7a, + 0xf9, 0xef, 0x2b, 0x79, 0x09, 0x4c, 0xef, 0x63, 0x82, 0xfc, 0x75, 0x4c, 0x0f, 0x70, 0x1b, 0xcc, + 0xd0, 0x37, 0x95, 0xc3, 0x76, 0xf1, 0xe5, 0xb3, 0x16, 0xc7, 0xf8, 0x0b, 0x51, 0x8e, 0xb8, 0x99, + 0xaa, 0x3e, 0x78, 0x73, 0xf6, 0xb1, 0xbf, 0x6d, 0x7f, 0x0c, 0x83, 0x39, 0xd6, 0xdc, 0x25, 0xa3, + 0x65, 0x58, 0x0e, 0xfc, 0x9a, 0x03, 0x71, 0xcb, 0xb4, 0x4f, 0x67, 0x8d, 0x3b, 0x6f, 0xd6, 0x74, + 0x97, 0xfb, 0xb8, 0x2f, 0x5e, 0x0c, 0xa0, 0xae, 0x62, 0xcb, 0x24, 0xc8, 0x6a, 0x92, 0xce, 0x20, + 0xd7, 0xc0, 0xf5, 0x64, 0x23, 0x08, 0x2c, 0xd3, 0xf6, 0x07, 0xf0, 0x2b, 0x0e, 0x40, 0xcb, 0x38, + 0xf0, 0x89, 0xf4, 0x26, 0x6a, 0x99, 0xb8, 0xc6, 0xd6, 0xfc, 0xea, 0xd8, 0x58, 0xe4, 0xd8, 0xe7, + 0x02, 0xfd, 0xa9, 0x8f, 0xfb, 0xe2, 0xa5, 0x71, 0xf0, 0x50, 0xac, 0x6c, 0xc1, 0x8e, 0x7b, 0x49, + 0x8f, 0xdd, 0xc1, 0xe1, 0x2d, 0xe3, 0xc0, 0x2f, 0x17, 0x35, 0x7f, 0xc9, 0x81, 0x44, 0xc5, 0x9b, + 0x26, 0x56, 0xbf, 0xcf, 0x01, 0x9b, 0x2e, 0x3f, 0x36, 0xee, 0xbc, 0xd8, 0x6e, 0xb2, 0xd8, 0x56, + 0x86, 0x70, 0x43, 0x61, 0x2d, 0x0d, 0x0d, 0x73, 0x30, 0xa2, 0x04, 0xb5, 0xb1, 0x68, 0x7e, 0xf7, + 0x67, 0x98, 0x05, 0x73, 0x0f, 0x44, 0x3f, 0x6b, 0xe3, 0x56, 0xdb, 0xf2, 0xa2, 0x48, 0xc8, 0xf2, + 0x64, 0x1f, 0x34, 0xc7, 0x7d, 0x91, 0xa7, 0xf8, 0x41, 0x34, 0x2a, 0x63, 0x84, 0x55, 0x10, 0x23, + 0x7b, 0x2d, 0xe4, 0xec, 0xe1, 0x06, 0xfd, 0x01, 0x12, 0x13, 0x0d, 0x14, 0xa5, 0x5f, 0x3c, 0xa5, + 0x08, 0x28, 0x0c, 0x78, 0x61, 0x97, 0x03, 0xf3, 0xee, 0x94, 0xe9, 0x03, 0xa9, 0x29, 0x4f, 0xaa, + 0x3a, 0xb1, 0x54, 0x72, 0x98, 0x67, 0xa8, 0xbe, 0x17, 0x59, 0x7d, 0x87, 0x3c, 0x24, 0x75, 0xce, + 0x35, 0x68, 0xfe, 0xf9, 0xca, 0x9f, 0x1c, 0x00, 0x81, 0xaf, 0xcc, 0xab, 0x60, 0xa5, 0x52, 0xd4, + 0x14, 0xbd, 0x58, 0xd2, 0xf2, 0xc5, 0x82, 0x7e, 0xa7, 0x50, 0x2e, 0x29, 0x5b, 0xf9, 0xed, 0xbc, + 0x92, 0xe3, 0x43, 0xa9, 0x85, 0x6e, 0x2f, 0x1d, 0xa7, 0x8e, 0x8a, 0x2b, 0x02, 0x25, 0xb0, 0x10, + 0xf4, 0xbe, 0xab, 0x94, 0x79, 0x2e, 0x35, 0xd7, 0xed, 0xa5, 0x63, 0xd4, 0xeb, 0x2e, 0x72, 0xe0, + 0x15, 0xb0, 0x18, 0xf4, 0xc9, 0xca, 0x65, 0x2d, 0x9b, 0x2f, 0xf0, 0xe1, 0xd4, 0x85, 0x6e, 0x2f, + 0x3d, 0x47, 0xfd, 0xb2, 0x6c, 0x25, 0xa6, 0xc1, 0x7c, 0xd0, 0xb7, 0x50, 0xe4, 0xa7, 0x52, 0x89, + 0x6e, 0x2f, 0x3d, 0x4b, 0xdd, 0x0a, 0x18, 0x6e, 0x80, 0xe4, 0xb0, 0x87, 0xbe, 0x93, 0xd7, 0x6e, + 0xe9, 0x15, 0x45, 0x2b, 0xf2, 0x91, 0xd4, 0x52, 0xb7, 0x97, 0xe6, 0x7d, 0x5f, 0x7f, 0x7f, 0xa5, + 0x22, 0x0f, 0xbf, 0x11, 0x42, 0x57, 0x7e, 0x0e, 0x83, 0xf9, 0xe1, 0x4f, 0x1c, 0x98, 0x01, 0xff, + 0x2b, 0xa9, 0xc5, 0x52, 0xb1, 0x9c, 0xbd, 0xad, 0x97, 0xb5, 0xac, 0x76, 0xa7, 0x3c, 0x92, 0xb0, + 0x97, 0x0a, 0x75, 0x2e, 0x98, 0x0d, 0x78, 0x13, 0x08, 0xa3, 0xfe, 0x39, 0xa5, 0x54, 0x2c, 0xe7, + 0x35, 0xbd, 0xa4, 0xa8, 0xf9, 0x62, 0x8e, 0xe7, 0x52, 0x2b, 0xdd, 0x5e, 0x7a, 0x91, 0x42, 0x86, + 0x86, 0x0a, 0xbe, 0x0b, 0xfe, 0x3f, 0x0a, 0xae, 0x14, 0xb5, 0x7c, 0xe1, 0x43, 0x1f, 0x1b, 0x4e, + 0x2d, 0x77, 0x7b, 0x69, 0x48, 0xb1, 0x95, 0xc0, 0x04, 0xc0, 0xab, 0x60, 0x79, 0x14, 0x5a, 0xca, + 0x96, 0xcb, 0x4a, 0x8e, 0x9f, 0x4a, 0xf1, 0xdd, 0x5e, 0x3a, 0x41, 0x31, 0x25, 0xc3, 0x71, 0x50, + 0x0d, 0x5e, 0x07, 0xc9, 0x51, 0x6f, 0x55, 0xf9, 0x48, 0xd9, 0xd2, 0x94, 0x1c, 0x1f, 0x49, 0xc1, + 0x6e, 0x2f, 0x3d, 0x4f, 0xfd, 0x55, 0xf4, 0x09, 0xaa, 0x12, 0x74, 0x26, 0xff, 0x76, 0x36, 0x7f, + 0x5b, 0xc9, 0xf1, 0xd3, 0x41, 0xfe, 0x6d, 0xc3, 0x6c, 0xa0, 0x1a, 0x2d, 0xa7, 0x5c, 0x38, 0x7c, + 0x21, 0x84, 0x9e, 0xbd, 0x10, 0x42, 0x5f, 0x1c, 0x09, 0xa1, 0xc3, 0x23, 0x81, 0x7b, 0x7a, 0x24, + 0x70, 0x7f, 0x1c, 0x09, 0xdc, 0xa3, 0x97, 0x42, 0xe8, 0xe9, 0x4b, 0x21, 0xf4, 0xec, 0xa5, 0x10, + 0xba, 0xf7, 0xcf, 0x0b, 0xf1, 0xc0, 0xfb, 0x17, 0xce, 0xeb, 0xe7, 0xdd, 0xa8, 0xb7, 0x43, 0xde, + 0xfc, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x2e, 0xc3, 0x29, 0x39, 0xdd, 0x0d, 0x00, 0x00, } func (this *TextProposal) Equal(that interface{}) bool { @@ -709,7 +709,7 @@ func (this *TallyResult) Equal(that interface{}) bool { } return true } -func (m *SubVote) Marshal() (dAtA []byte, err error) { +func (m *WeightedVoteOption) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -719,20 +719,20 @@ func (m *SubVote) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *SubVote) MarshalTo(dAtA []byte) (int, error) { +func (m *WeightedVoteOption) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *SubVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *WeightedVoteOption) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l { - size := m.Rate.Size() + size := m.Weight.Size() i -= size - if _, err := m.Rate.MarshalTo(dAtA[i:]); err != nil { + if _, err := m.Weight.MarshalTo(dAtA[i:]); err != nil { return 0, err } i = encodeVarintGov(dAtA, i, uint64(size)) @@ -1017,10 +1017,10 @@ func (m *Vote) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.SubVotes) > 0 { - for iNdEx := len(m.SubVotes) - 1; iNdEx >= 0; iNdEx-- { + if len(m.Options) > 0 { + for iNdEx := len(m.Options) - 1; iNdEx >= 0; iNdEx-- { { - size, err := m.SubVotes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + size, err := m.Options[iNdEx].MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -1186,7 +1186,7 @@ func encodeVarintGov(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } -func (m *SubVote) Size() (n int) { +func (m *WeightedVoteOption) Size() (n int) { if m == nil { return 0 } @@ -1195,7 +1195,7 @@ func (m *SubVote) Size() (n int) { if m.Option != 0 { n += 1 + sovGov(uint64(m.Option)) } - l = m.Rate.Size() + l = m.Weight.Size() n += 1 + l + sovGov(uint64(l)) return n } @@ -1304,8 +1304,8 @@ func (m *Vote) Size() (n int) { if l > 0 { n += 1 + l + sovGov(uint64(l)) } - if len(m.SubVotes) > 0 { - for _, e := range m.SubVotes { + if len(m.Options) > 0 { + for _, e := range m.Options { l = e.Size() n += 1 + l + sovGov(uint64(l)) } @@ -1362,7 +1362,7 @@ func sovGov(x uint64) (n int) { func sozGov(x uint64) (n int) { return sovGov(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } -func (m *SubVote) Unmarshal(dAtA []byte) error { +func (m *WeightedVoteOption) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1385,10 +1385,10 @@ func (m *SubVote) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: SubVote: wiretype end group for non-group") + return fmt.Errorf("proto: WeightedVoteOption: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: SubVote: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: WeightedVoteOption: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -1412,7 +1412,7 @@ func (m *SubVote) Unmarshal(dAtA []byte) error { } case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Rate", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Weight", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1440,7 +1440,7 @@ func (m *SubVote) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Rate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Weight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -2320,7 +2320,7 @@ func (m *Vote) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SubVotes", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -2347,8 +2347,8 @@ func (m *Vote) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.SubVotes = append(m.SubVotes, SubVote{}) - if err := m.SubVotes[len(m.SubVotes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Options = append(m.Options, WeightedVoteOption{}) + if err := m.Options[len(m.Options)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/x/gov/types/msgs.go b/x/gov/types/msgs.go index 49ed6b734d7f..2cb3db539581 100644 --- a/x/gov/types/msgs.go +++ b/x/gov/types/msgs.go @@ -177,8 +177,8 @@ func (msg MsgDeposit) GetSigners() []sdk.AccAddress { // NewMsgVote creates a message to cast a vote on an active proposal //nolint:interfacer -func NewMsgVote(voter sdk.AccAddress, proposalID uint64, subVotes []SubVote) *MsgVote { - return &MsgVote{proposalID, voter.String(), subVotes} +func NewMsgVote(voter sdk.AccAddress, proposalID uint64, options WeightedVoteOptions) *MsgVote { + return &MsgVote{proposalID, voter.String(), options} } // Route implements Msg @@ -193,14 +193,25 @@ func (msg MsgVote) ValidateBasic() error { return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Voter) } - if len(msg.SubVotes) == 0 { - return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, SubVotes(msg.SubVotes).String()) + if len(msg.Options) == 0 { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, WeightedVoteOptions(msg.Options).String()) } - for _, subvote := range msg.SubVotes { - if !ValidSubVote(subvote) { - return sdkerrors.Wrap(ErrInvalidVote, subvote.String()) + totalWeight := sdk.NewDec(0) + usedOptions := make(map[VoteOption]bool) + for _, option := range msg.Options { + if !ValidWeightedVoteOption(option) { + return sdkerrors.Wrap(ErrInvalidVote, option.String()) } + totalWeight = totalWeight.Add(option.Weight) + if usedOptions[option.Option] { + return sdkerrors.Wrap(ErrInvalidVote, "Duplicated vote option") + } + usedOptions[option.Option] = true + } + + if totalWeight.GT(sdk.NewDec(1)) { + return sdkerrors.Wrap(ErrInvalidVote, "Total weight overflow 1.00") } return nil diff --git a/x/gov/types/msgs_test.go b/x/gov/types/msgs_test.go index a974e4d44efd..c457c564fed1 100644 --- a/x/gov/types/msgs_test.go +++ b/x/gov/types/msgs_test.go @@ -97,22 +97,34 @@ func TestMsgVote(t *testing.T) { tests := []struct { proposalID uint64 voterAddr sdk.AccAddress - subvotes SubVotes + options WeightedVoteOptions expectPass bool }{ - {0, addrs[0], SubVotes{NewSubVote(OptionYes, 1)}, true}, - {0, sdk.AccAddress{}, SubVotes{NewSubVote(OptionYes, 1)}, false}, - {0, addrs[0], SubVotes{NewSubVote(OptionNo, 1)}, true}, - {0, addrs[0], SubVotes{NewSubVote(OptionNoWithVeto, 1)}, true}, - {0, addrs[0], SubVotes{NewSubVote(OptionAbstain, 1)}, true}, - {0, addrs[0], SubVotes{NewSubVote(OptionYes, 1), NewSubVote(OptionAbstain, 1)}, true}, - {0, addrs[0], SubVotes{NewSubVote(OptionYes, 0)}, false}, - {0, addrs[0], SubVotes{}, false}, - {0, addrs[0], SubVotes{NewSubVote(VoteOption(0x13), 1)}, false}, + {0, addrs[0], NewNonSplitVoteOption(OptionYes), true}, + {0, sdk.AccAddress{}, NewNonSplitVoteOption(OptionYes), false}, + {0, addrs[0], NewNonSplitVoteOption(OptionNo), true}, + {0, addrs[0], NewNonSplitVoteOption(OptionNoWithVeto), true}, + {0, addrs[0], NewNonSplitVoteOption(OptionAbstain), true}, + {0, addrs[0], WeightedVoteOptions{ // weight sum > 1 + WeightedVoteOption{Option: OptionYes, Weight: sdk.NewDec(1)}, + WeightedVoteOption{Option: OptionAbstain, Weight: sdk.NewDec(1)}, + }, false}, + {0, addrs[0], WeightedVoteOptions{ // duplicate option + WeightedVoteOption{Option: OptionYes, Weight: sdk.NewDecWithPrec(5, 1)}, + WeightedVoteOption{Option: OptionYes, Weight: sdk.NewDecWithPrec(5, 1)}, + }, false}, + {0, addrs[0], WeightedVoteOptions{ // zero weight + WeightedVoteOption{Option: OptionYes, Weight: sdk.NewDec(0)}, + }, false}, + {0, addrs[0], WeightedVoteOptions{ // negative weight + WeightedVoteOption{Option: OptionYes, Weight: sdk.NewDec(-1)}, + }, false}, + {0, addrs[0], WeightedVoteOptions{}, false}, + {0, addrs[0], NewNonSplitVoteOption(VoteOption(0x13)), false}, } for i, tc := range tests { - msg := NewMsgVote(tc.voterAddr, tc.proposalID, tc.subvotes) + msg := NewMsgVote(tc.voterAddr, tc.proposalID, tc.options) if tc.expectPass { require.Nil(t, msg.ValidateBasic(), "test: %v", i) } else { diff --git a/x/gov/types/tally.go b/x/gov/types/tally.go index 294de078d23b..3d5efe51cad3 100644 --- a/x/gov/types/tally.go +++ b/x/gov/types/tally.go @@ -8,23 +8,23 @@ import ( // ValidatorGovInfo used for tallying type ValidatorGovInfo struct { - Address sdk.ValAddress // address of the validator operator - BondedTokens sdk.Int // Power of a Validator - DelegatorShares sdk.Dec // Total outstanding delegator shares - DelegatorDeductions sdk.Dec // Delegator deductions from validator's delegators voting independently - Vote SubVotes // Vote of the validator + Address sdk.ValAddress // address of the validator operator + BondedTokens sdk.Int // Power of a Validator + DelegatorShares sdk.Dec // Total outstanding delegator shares + DelegatorDeductions sdk.Dec // Delegator deductions from validator's delegators voting independently + Vote WeightedVoteOptions // Vote of the validator } // NewValidatorGovInfo creates a ValidatorGovInfo instance func NewValidatorGovInfo(address sdk.ValAddress, bondedTokens sdk.Int, delegatorShares, - delegatorDeductions sdk.Dec, subvotes SubVotes) ValidatorGovInfo { + delegatorDeductions sdk.Dec, options WeightedVoteOptions) ValidatorGovInfo { return ValidatorGovInfo{ Address: address, BondedTokens: bondedTokens, DelegatorShares: delegatorShares, DelegatorDeductions: delegatorDeductions, - Vote: subvotes, + Vote: options, } } diff --git a/x/gov/types/tx.pb.go b/x/gov/types/tx.pb.go index f595a954a2a3..d77104ae7037 100644 --- a/x/gov/types/tx.pb.go +++ b/x/gov/types/tx.pb.go @@ -119,9 +119,9 @@ func (m *MsgSubmitProposalResponse) GetProposalId() uint64 { // MsgVote defines a message to cast a vote. type MsgVote struct { - ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id" yaml:"proposal_id"` - Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` - SubVotes []SubVote `protobuf:"bytes,3,rep,name=sub_votes,json=subVotes,proto3" json:"sub_votes"` + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id" yaml:"proposal_id"` + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` + Options []WeightedVoteOption `protobuf:"bytes,3,rep,name=options,proto3" json:"options"` } func (m *MsgVote) Reset() { *m = MsgVote{} } @@ -281,45 +281,45 @@ func init() { func init() { proto.RegisterFile("cosmos/gov/v1beta1/tx.proto", fileDescriptor_3c053992595e3dce) } var fileDescriptor_3c053992595e3dce = []byte{ - // 593 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x31, 0x6f, 0xd3, 0x40, - 0x14, 0xb6, 0x93, 0xd2, 0xb4, 0x17, 0xa9, 0xa5, 0xa7, 0x08, 0x25, 0x4e, 0x65, 0x47, 0x46, 0x45, - 0x59, 0x62, 0xd3, 0xb0, 0x15, 0x09, 0x09, 0x17, 0x21, 0x40, 0x8a, 0x04, 0xae, 0xc4, 0xc0, 0x12, - 0xd9, 0x8e, 0x6b, 0x2c, 0x12, 0x3f, 0x2b, 0x77, 0x8e, 0x9a, 0x8d, 0x11, 0x31, 0x00, 0x23, 0x63, - 0x66, 0x66, 0x16, 0xfe, 0x41, 0xc5, 0xd4, 0x91, 0x01, 0x05, 0x94, 0x2c, 0xc0, 0xd8, 0x5f, 0x80, - 0xec, 0xbb, 0x4b, 0xab, 0x26, 0x8d, 0x40, 0xea, 0x94, 0xbc, 0xf7, 0xdd, 0xf7, 0xe9, 0xbe, 0xef, - 0x3d, 0x1f, 0xaa, 0x7a, 0x40, 0x7a, 0x40, 0xcc, 0x00, 0x06, 0xe6, 0x60, 0xd7, 0xf5, 0xa9, 0xb3, - 0x6b, 0xd2, 0x23, 0x23, 0xee, 0x03, 0x05, 0x8c, 0x19, 0x68, 0x04, 0x30, 0x30, 0x38, 0xa8, 0xa8, - 0x9c, 0xe0, 0x3a, 0xc4, 0x9f, 0x31, 0x3c, 0x08, 0x23, 0xc6, 0x51, 0xb6, 0x17, 0x08, 0xa6, 0x7c, - 0x86, 0x56, 0x18, 0xda, 0xce, 0x2a, 0x93, 0xcb, 0x33, 0xa8, 0x14, 0x40, 0x00, 0xac, 0x9f, 0xfe, - 0x13, 0x84, 0x00, 0x20, 0xe8, 0xfa, 0x66, 0x56, 0xb9, 0xc9, 0xa1, 0xe9, 0x44, 0x43, 0x06, 0xe9, - 0xef, 0x73, 0x68, 0xab, 0x45, 0x82, 0x83, 0xc4, 0xed, 0x85, 0xf4, 0x69, 0x1f, 0x62, 0x20, 0x4e, - 0x17, 0xdf, 0x45, 0x05, 0x0f, 0x22, 0xea, 0x47, 0xb4, 0x2c, 0xd7, 0xe4, 0x7a, 0xb1, 0x59, 0x32, - 0x98, 0x84, 0x21, 0x24, 0x8c, 0xfb, 0xd1, 0xd0, 0x2a, 0x7e, 0xfd, 0xdc, 0x28, 0xec, 0xb3, 0x83, - 0xb6, 0x60, 0xe0, 0x77, 0x32, 0xda, 0x0c, 0xa3, 0x90, 0x86, 0x4e, 0xb7, 0xdd, 0xf1, 0x63, 0x20, - 0x21, 0x2d, 0xe7, 0x6a, 0xf9, 0x7a, 0xb1, 0x59, 0x31, 0xf8, 0x65, 0x53, 0xdf, 0x22, 0x0c, 0x63, - 0x1f, 0xc2, 0xc8, 0x7a, 0x72, 0x3c, 0xd6, 0xa4, 0xd3, 0xb1, 0x76, 0x63, 0xe8, 0xf4, 0xba, 0x7b, - 0xfa, 0x05, 0xbe, 0xfe, 0xe9, 0x87, 0x56, 0x0f, 0x42, 0xfa, 0x32, 0x71, 0x0d, 0x0f, 0x7a, 0xdc, - 0x33, 0xff, 0x69, 0x90, 0xce, 0x2b, 0x93, 0x0e, 0x63, 0x9f, 0x64, 0x52, 0xc4, 0xde, 0xe0, 0xec, - 0x07, 0x8c, 0x8c, 0x15, 0xb4, 0x16, 0x67, 0xce, 0xfc, 0x7e, 0x39, 0x5f, 0x93, 0xeb, 0xeb, 0xf6, - 0xac, 0xde, 0xbb, 0xfe, 0x66, 0xa4, 0x49, 0x1f, 0x47, 0x9a, 0xf4, 0x6b, 0xa4, 0x49, 0xaf, 0xbf, - 0xd7, 0x24, 0xdd, 0x43, 0x95, 0xb9, 0x40, 0x6c, 0x9f, 0xc4, 0x10, 0x11, 0x1f, 0x3f, 0x44, 0xc5, - 0x98, 0xf7, 0xda, 0x61, 0x27, 0x0b, 0x67, 0xc5, 0xda, 0xf9, 0x33, 0xd6, 0xce, 0xb7, 0x4f, 0xc7, - 0x1a, 0x66, 0x36, 0xce, 0x35, 0x75, 0x1b, 0x89, 0xea, 0x71, 0x47, 0xff, 0x22, 0xa3, 0x42, 0x8b, - 0x04, 0xcf, 0x81, 0x5e, 0x99, 0x26, 0x2e, 0xa1, 0x6b, 0x03, 0xa0, 0x7e, 0xbf, 0x9c, 0xcb, 0x3c, - 0xb2, 0x02, 0xdf, 0x43, 0xeb, 0x24, 0x71, 0xdb, 0x69, 0x41, 0xca, 0xf9, 0x6c, 0x0c, 0x55, 0x63, - 0x7e, 0x25, 0x8d, 0x83, 0xc4, 0x4d, 0x6f, 0x63, 0xad, 0xa4, 0x83, 0xb0, 0xd7, 0x08, 0x2b, 0xc9, - 0x82, 0x80, 0xb6, 0xd0, 0x26, 0xbf, 0xba, 0x88, 0x45, 0xff, 0x2d, 0x23, 0xd4, 0x22, 0x81, 0x08, - 0xfc, 0xaa, 0x1c, 0x6d, 0xa3, 0x75, 0xbe, 0x00, 0x20, 0x5c, 0x9d, 0x35, 0xb0, 0x87, 0x56, 0x9d, - 0x1e, 0x24, 0x11, 0xe5, 0xb6, 0x96, 0x6c, 0xd7, 0xed, 0xd4, 0xd4, 0x7f, 0xed, 0x10, 0x97, 0x5e, - 0x60, 0xbf, 0x84, 0xf0, 0x99, 0x55, 0x91, 0x40, 0xf3, 0x6d, 0x0e, 0xe5, 0x5b, 0x24, 0xc0, 0x87, - 0x68, 0xe3, 0xc2, 0xb7, 0xb4, 0xb3, 0x28, 0xed, 0xb9, 0x0d, 0x53, 0x1a, 0xff, 0x74, 0x6c, 0xb6, - 0x88, 0x8f, 0xd0, 0x4a, 0xb6, 0x3c, 0xd5, 0x4b, 0x68, 0x29, 0xa8, 0xdc, 0x5c, 0x02, 0xce, 0x94, - 0x9e, 0xa1, 0x82, 0x98, 0x9b, 0x7a, 0xc9, 0x79, 0x8e, 0x2b, 0xb7, 0x96, 0xe3, 0x42, 0xd2, 0xb2, - 0x8e, 0x27, 0xaa, 0x7c, 0x32, 0x51, 0xe5, 0x9f, 0x13, 0x55, 0xfe, 0x30, 0x55, 0xa5, 0x93, 0xa9, - 0x2a, 0x7d, 0x9b, 0xaa, 0xd2, 0x8b, 0xe5, 0x03, 0x38, 0xca, 0x1e, 0xbc, 0x6c, 0x0c, 0xee, 0x6a, - 0xf6, 0xd2, 0xdc, 0xf9, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x7e, 0x2c, 0x84, 0x48, 0x5c, 0x05, 0x00, - 0x00, + // 596 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x3d, 0x6f, 0xd3, 0x50, + 0x14, 0xb5, 0x93, 0xd2, 0xd0, 0x17, 0xa9, 0xa5, 0x4f, 0x11, 0x4a, 0xd3, 0xca, 0x8e, 0x8c, 0x5a, + 0x65, 0xa9, 0x4d, 0xcb, 0x56, 0x26, 0x5c, 0x54, 0x01, 0x52, 0x04, 0x18, 0x09, 0x24, 0x96, 0xca, + 0x76, 0x5e, 0x5f, 0x2d, 0x12, 0x5f, 0x2b, 0xef, 0x25, 0x6a, 0x36, 0x46, 0xc4, 0x00, 0x8c, 0x8c, + 0x9d, 0x99, 0xf9, 0x03, 0x6c, 0x15, 0x53, 0x47, 0x06, 0x14, 0x50, 0xbb, 0x00, 0x63, 0x7f, 0x01, + 0xf2, 0xfb, 0x48, 0xab, 0x36, 0x8d, 0x40, 0xea, 0x94, 0xdc, 0x7b, 0xee, 0x39, 0xf2, 0x39, 0xf7, + 0xda, 0x68, 0x31, 0x06, 0xd6, 0x01, 0xe6, 0x51, 0xe8, 0x7b, 0xfd, 0xb5, 0x88, 0xf0, 0x70, 0xcd, + 0xe3, 0x7b, 0x6e, 0xd6, 0x05, 0x0e, 0x18, 0x4b, 0xd0, 0xa5, 0xd0, 0x77, 0x15, 0x58, 0xb3, 0x14, + 0x21, 0x0a, 0x19, 0x19, 0x31, 0x62, 0x48, 0x52, 0xc9, 0xa9, 0x2d, 0x8d, 0x11, 0xcc, 0xf9, 0x12, + 0x5d, 0x90, 0xe8, 0xb6, 0xa8, 0x3c, 0x25, 0x2f, 0xa1, 0x0a, 0x05, 0x0a, 0xb2, 0x9f, 0xff, 0xd3, + 0x04, 0x0a, 0x40, 0xdb, 0xc4, 0x13, 0x55, 0xd4, 0xdb, 0xf1, 0xc2, 0x74, 0x20, 0x21, 0xe7, 0x7d, + 0x01, 0xcd, 0x37, 0x19, 0x7d, 0xd6, 0x8b, 0x3a, 0x09, 0x7f, 0xd2, 0x85, 0x0c, 0x58, 0xd8, 0xc6, + 0x77, 0x51, 0x29, 0x86, 0x94, 0x93, 0x94, 0x57, 0xcd, 0xba, 0xd9, 0x28, 0xaf, 0x57, 0x5c, 0x29, + 0xe1, 0x6a, 0x09, 0xf7, 0x5e, 0x3a, 0xf0, 0xcb, 0x5f, 0x3f, 0xaf, 0x96, 0x36, 0xe5, 0x60, 0xa0, + 0x19, 0xf8, 0x9d, 0x89, 0xe6, 0x92, 0x34, 0xe1, 0x49, 0xd8, 0xde, 0x6e, 0x91, 0x0c, 0x58, 0xc2, + 0xab, 0x85, 0x7a, 0xb1, 0x51, 0x5e, 0x5f, 0x70, 0xd5, 0xc3, 0xe6, 0xbe, 0x75, 0x18, 0xee, 0x26, + 0x24, 0xa9, 0xff, 0xe8, 0x60, 0x68, 0x1b, 0x27, 0x43, 0xfb, 0xe6, 0x20, 0xec, 0xb4, 0x37, 0x9c, + 0x73, 0x7c, 0xe7, 0xd3, 0x0f, 0xbb, 0x41, 0x13, 0xbe, 0xdb, 0x8b, 0xdc, 0x18, 0x3a, 0xca, 0xb3, + 0xfa, 0x59, 0x65, 0xad, 0x57, 0x1e, 0x1f, 0x64, 0x84, 0x09, 0x29, 0x16, 0xcc, 0x2a, 0xf6, 0x7d, + 0x49, 0xc6, 0x35, 0x74, 0x3d, 0x13, 0xce, 0x48, 0xb7, 0x5a, 0xac, 0x9b, 0x8d, 0x99, 0x60, 0x54, + 0x6f, 0xdc, 0x78, 0xb3, 0x6f, 0x1b, 0x1f, 0xf7, 0x6d, 0xe3, 0xd7, 0xbe, 0x6d, 0xbc, 0xfe, 0x5e, + 0x37, 0x9c, 0x18, 0x2d, 0x5c, 0x08, 0x24, 0x20, 0x2c, 0x83, 0x94, 0x11, 0xbc, 0x85, 0xca, 0x99, + 0xea, 0x6d, 0x27, 0x2d, 0x11, 0xce, 0x94, 0xbf, 0xfc, 0x67, 0x68, 0x9f, 0x6d, 0x9f, 0x0c, 0x6d, + 0x2c, 0x6d, 0x9c, 0x69, 0x3a, 0x01, 0xd2, 0xd5, 0xc3, 0x96, 0xf3, 0xc5, 0x44, 0xa5, 0x26, 0xa3, + 0xcf, 0x81, 0x5f, 0x99, 0x26, 0xae, 0xa0, 0x6b, 0x7d, 0xe0, 0xa4, 0x5b, 0x2d, 0x08, 0x8f, 0xb2, + 0xc0, 0x5b, 0xa8, 0x04, 0x19, 0x4f, 0x20, 0x65, 0xd5, 0xa2, 0x58, 0xc2, 0x8a, 0x7b, 0xf1, 0x20, + 0xdd, 0x17, 0x24, 0xa1, 0xbb, 0x9c, 0xb4, 0xf2, 0x07, 0x7a, 0x2c, 0xc6, 0xfd, 0xa9, 0x7c, 0x23, + 0x81, 0x26, 0x8f, 0x09, 0x6a, 0x1e, 0xcd, 0x29, 0x0b, 0x3a, 0x1e, 0xe7, 0xb7, 0x89, 0x50, 0x93, + 0x51, 0x1d, 0xfc, 0x55, 0x39, 0x5b, 0x42, 0x33, 0xea, 0x10, 0x40, 0xbb, 0x3b, 0x6d, 0xe0, 0x18, + 0x4d, 0x87, 0x1d, 0xe8, 0xa5, 0x5c, 0x19, 0x9c, 0x70, 0x65, 0xb7, 0x73, 0x4f, 0xff, 0x75, 0x4b, + 0x4a, 0x7a, 0x8c, 0xfd, 0x0a, 0xc2, 0xa7, 0x56, 0x75, 0x02, 0xeb, 0x6f, 0x0b, 0xa8, 0xd8, 0x64, + 0x14, 0xef, 0xa0, 0xd9, 0x73, 0xef, 0xd4, 0xf2, 0xb8, 0xdc, 0x2f, 0x5c, 0x5a, 0x6d, 0xf5, 0x9f, + 0xc6, 0x46, 0x07, 0xf9, 0x00, 0x4d, 0x89, 0x23, 0x5a, 0xbc, 0x84, 0x96, 0x83, 0xb5, 0x5b, 0x13, + 0xc0, 0x91, 0xd2, 0x53, 0x54, 0xd2, 0x7b, 0xb3, 0x2e, 0x99, 0x57, 0x78, 0x6d, 0x65, 0x32, 0xae, + 0x25, 0x7d, 0xff, 0xe0, 0xc8, 0x32, 0x0f, 0x8f, 0x2c, 0xf3, 0xe7, 0x91, 0x65, 0x7e, 0x38, 0xb6, + 0x8c, 0xc3, 0x63, 0xcb, 0xf8, 0x76, 0x6c, 0x19, 0x2f, 0x27, 0x2f, 0x60, 0x4f, 0x7c, 0xf8, 0xc4, + 0x1a, 0xa2, 0x69, 0xf1, 0xc5, 0xb9, 0xf3, 0x37, 0x00, 0x00, 0xff, 0xff, 0xb6, 0x98, 0x0c, 0x31, + 0x64, 0x05, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -584,10 +584,10 @@ func (m *MsgVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.SubVotes) > 0 { - for iNdEx := len(m.SubVotes) - 1; iNdEx >= 0; iNdEx-- { + if len(m.Options) > 0 { + for iNdEx := len(m.Options) - 1; iNdEx >= 0; iNdEx-- { { - size, err := m.SubVotes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + size, err := m.Options[iNdEx].MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -767,8 +767,8 @@ func (m *MsgVote) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - if len(m.SubVotes) > 0 { - for _, e := range m.SubVotes { + if len(m.Options) > 0 { + for _, e := range m.Options { l = e.Size() n += 1 + l + sovTx(uint64(l)) } @@ -1131,7 +1131,7 @@ func (m *MsgVote) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SubVotes", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1158,8 +1158,8 @@ func (m *MsgVote) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.SubVotes = append(m.SubVotes, SubVote{}) - if err := m.SubVotes[len(m.SubVotes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Options = append(m.Options, WeightedVoteOption{}) + if err := m.Options[len(m.Options)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/x/gov/types/vote.go b/x/gov/types/vote.go index 5a3a399019e5..dc88be0ec7d2 100644 --- a/x/gov/types/vote.go +++ b/x/gov/types/vote.go @@ -12,8 +12,8 @@ import ( // NewVote creates a new Vote instance //nolint:interfacer -func NewVote(proposalID uint64, voter sdk.AccAddress, subvotes []SubVote) Vote { - return Vote{proposalID, voter.String(), subvotes} +func NewVote(proposalID uint64, voter sdk.AccAddress, options WeightedVoteOptions) Vote { + return Vote{proposalID, voter.String(), options} } func (v Vote) String() string { @@ -45,7 +45,7 @@ func (v Votes) String() string { } out := fmt.Sprintf("Votes for Proposal %d:", v[0].ProposalId) for _, vot := range v { - out += fmt.Sprintf("\n %s: %s", vot.Voter, vot.SubVotes) + out += fmt.Sprintf("\n %s: %s", vot.Voter, vot.Options) } return out } @@ -55,31 +55,31 @@ func (v Vote) Empty() bool { return v.String() == Vote{}.String() } -// NewSubVote creates a new Vote instance +// NewNonSplitVoteOption creates a single option vote with weight 1 //nolint:interfacer -func NewSubVote(option VoteOption, rate int64) SubVote { - return SubVote{option, sdk.NewDec(rate)} +func NewNonSplitVoteOption(option VoteOption) WeightedVoteOptions { + return WeightedVoteOptions{{option, sdk.NewDec(1)}} } -func (v SubVote) String() string { +func (v WeightedVoteOption) String() string { out, _ := json.Marshal(v) return string(out) } -// SubVotes describes array of SubVote -type SubVotes []SubVote +// WeightedVoteOptions describes array of WeightedVoteOptions +type WeightedVoteOptions []WeightedVoteOption -func (v SubVotes) String() string { +func (v WeightedVoteOptions) String() string { out, _ := json.Marshal(v) return string(out) } -// ValidSubVote returns true if the sub vote is valid and false otherwise. -func ValidSubVote(subvote SubVote) bool { - if !subvote.Rate.IsPositive() { +// ValidWeightedVoteOption returns true if the sub vote is valid and false otherwise. +func ValidWeightedVoteOption(option WeightedVoteOption) bool { + if !option.Weight.IsPositive() || option.Weight.GT(sdk.NewDec(1)) { return false } - return ValidVoteOption(subvote.Option) + return ValidVoteOption(option.Option) } // VoteOptionFromString returns a VoteOption from a string. It returns an error @@ -92,29 +92,26 @@ func VoteOptionFromString(str string) (VoteOption, error) { return VoteOption(option), nil } -// SubVotesFromString returns a SubVotes from a string. It returns an error +// WeightedVoteOptionsFromString returns weighted vote options from string. It returns an error // if the string is invalid. -func SubVotesFromString(str string) (SubVotes, error) { - subvotes := SubVotes{} - for _, subvote := range strings.Split(str, ",") { - fields := strings.Split(subvote, "=") +func WeightedVoteOptionsFromString(str string) (WeightedVoteOptions, error) { + options := WeightedVoteOptions{} + for _, option := range strings.Split(str, ",") { + fields := strings.Split(option, "=") option, err := VoteOptionFromString(fields[0]) if err != nil { - return subvotes, err + return options, err } if len(fields) < 2 { - return subvotes, fmt.Errorf("rate field does not exist for %s opion", fields[0]) + return options, fmt.Errorf("weight field does not exist for %s option", fields[0]) } - rate, err := sdk.NewDecFromStr(fields[1]) + weight, err := sdk.NewDecFromStr(fields[1]) if err != nil { - return subvotes, err + return options, err } - subvotes = append(subvotes, SubVote{ - option, - rate, - }) + options = append(options, WeightedVoteOption{option, weight}) } - return subvotes, nil + return options, nil } // ValidVoteOption returns true if the vote option is valid and false otherwise. From 5a082584c936e8c032def5e60fde9c010ee4c94e Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Fri, 30 Oct 2020 23:28:34 +1000 Subject: [PATCH 011/152] Remove Div operation on tally() considering sum(Weight)=1 --- x/gov/keeper/tally.go | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/x/gov/keeper/tally.go b/x/gov/keeper/tally.go index 2598293a84ab..cc87d68ed9d2 100644 --- a/x/gov/keeper/tally.go +++ b/x/gov/keeper/tally.go @@ -60,17 +60,11 @@ func (keeper Keeper) Tally(ctx sdk.Context, proposal types.Proposal) (passes boo delegatorShare := delegation.GetShares().Quo(val.DelegatorShares) votingPower := delegatorShare.MulInt(val.BondedTokens) - totalRates := sdk.NewDec(0) for _, option := range vote.Options { - totalRates = totalRates.Add(option.Weight) - } - for _, option := range vote.Options { - subPower := sdk.NewDecFromBigInt(votingPower.BigInt().Div(votingPower.Mul(option.Weight).BigInt(), totalRates.BigInt())) + subPower := votingPower.Mul(option.Weight) results[option.Option] = results[option.Option].Add(subPower) - totalVotingPower = totalVotingPower.Add(subPower) } - // TODO how should handle remainder? - // TODO how should handle when totalRates == 0 + totalVotingPower = totalVotingPower.Add(votingPower) } return false @@ -90,17 +84,11 @@ func (keeper Keeper) Tally(ctx sdk.Context, proposal types.Proposal) (passes boo fractionAfterDeductions := sharesAfterDeductions.Quo(val.DelegatorShares) votingPower := fractionAfterDeductions.MulInt(val.BondedTokens) - totalRates := sdk.NewDec(0) - for _, option := range val.Vote { - totalRates = totalRates.Add(option.Weight) - } for _, option := range val.Vote { - subPower := sdk.NewDecFromBigInt(votingPower.BigInt().Div(votingPower.Mul(option.Weight).BigInt(), totalRates.BigInt())) + subPower := votingPower.Mul(option.Weight) results[option.Option] = results[option.Option].Add(subPower) - totalVotingPower = totalVotingPower.Add(subPower) - // TODO how should handle remainder? - // TODO how should handle when totalRates == 0 } + totalVotingPower = totalVotingPower.Add(votingPower) } tallyParams := keeper.GetTallyParams(ctx) From ee1988a4ba7d14da1970a8fb4b43dc8e46ef9fe6 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Tue, 3 Nov 2020 21:48:53 +1000 Subject: [PATCH 012/152] split MsgVote and MsgWeightedVote for backwards compatibility --- proto/cosmos/gov/v1beta1/tx.proto | 15 ++ simapp/params/weights.go | 1 + x/gov/client/cli/cli_test.go | 62 ++++- x/gov/client/cli/tx.go | 57 ++++- x/gov/client/rest/rest.go | 9 +- x/gov/client/rest/tx.go | 45 +++- x/gov/client/testutil/helpers.go | 2 +- x/gov/client/utils/query.go | 31 ++- x/gov/client/utils/query_test.go | 8 +- x/gov/handler.go | 4 + x/gov/keeper/msg_server.go | 30 +++ x/gov/simulation/operations.go | 121 +++++++++- x/gov/simulation/operations_test.go | 45 +++- x/gov/spec/04_events.md | 10 + x/gov/types/codec.go | 2 + x/gov/types/msgs.go | 58 ++++- x/gov/types/msgs_test.go | 30 ++- x/gov/types/tx.pb.go | 353 ++++++++++++++++++++++++---- 18 files changed, 805 insertions(+), 78 deletions(-) diff --git a/proto/cosmos/gov/v1beta1/tx.proto b/proto/cosmos/gov/v1beta1/tx.proto index 9d38203b9281..3fb754d14292 100644 --- a/proto/cosmos/gov/v1beta1/tx.proto +++ b/proto/cosmos/gov/v1beta1/tx.proto @@ -17,6 +17,9 @@ service Msg { // Vote defines a method to add a vote on a specific proposal. rpc Vote(MsgVote) returns (MsgVoteResponse); + // WeightedVote defines a method to add a weighted vote on a specific proposal. + rpc WeightedVote(MsgWeightedVote) returns (MsgVoteResponse); + // Deposit defines a method to add deposit on a specific proposal. rpc Deposit(MsgDeposit) returns (MsgDepositResponse); } @@ -50,6 +53,18 @@ message MsgVote { option (gogoproto.stringer) = false; option (gogoproto.goproto_getters) = false; + uint64 proposal_id = 1 [(gogoproto.moretags) = "yaml:\"proposal_id\""]; + string voter = 2; + VoteOption option = 3; +} + +// MsgVote defines a message to cast a vote. +message MsgWeightedVote { + option (gogoproto.equal) = false; + option (gogoproto.goproto_stringer) = false; + option (gogoproto.stringer) = false; + option (gogoproto.goproto_getters) = false; + uint64 proposal_id = 1 [(gogoproto.jsontag) = "proposal_id", (gogoproto.moretags) = "yaml:\"proposal_id\""]; string voter = 2; repeated WeightedVoteOption options = 3 [(gogoproto.nullable) = false]; diff --git a/simapp/params/weights.go b/simapp/params/weights.go index 0ba377b009b1..1f4a25eba4aa 100644 --- a/simapp/params/weights.go +++ b/simapp/params/weights.go @@ -10,6 +10,7 @@ const ( DefaultWeightMsgFundCommunityPool int = 50 DefaultWeightMsgDeposit int = 100 DefaultWeightMsgVote int = 67 + DefaultWeightMsgWeightedVote int = 33 DefaultWeightMsgUnjail int = 100 DefaultWeightMsgCreateValidator int = 100 DefaultWeightMsgEditValidator int = 5 diff --git a/x/gov/client/cli/cli_test.go b/x/gov/client/cli/cli_test.go index 0ccac645a6ec..4a35e2776ae6 100644 --- a/x/gov/client/cli/cli_test.go +++ b/x/gov/client/cli/cli_test.go @@ -779,6 +779,66 @@ func (s *IntegrationTestSuite) TestCmdQueryVote() { func (s *IntegrationTestSuite) TestNewCmdVote() { val := s.network.Validators[0] + testCases := []struct { + name string + args []string + expectErr bool + expectedCode uint32 + }{ + { + "invalid vote", + []string{}, + true, 0, + }, + { + "vote for invalid proposal", + []string{ + "10", + fmt.Sprintf("%s", "yes"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + false, 2, + }, + { + "valid vote", + []string{ + "1", + fmt.Sprintf("%s", "yes"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + false, 0, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.NewCmdVote() + clientCtx := val.ClientCtx + var txResp sdk.TxResponse + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestNewCmdWeightedVote() { + val := s.network.Validators[0] + testCases := []struct { name string args []string @@ -843,7 +903,7 @@ func (s *IntegrationTestSuite) TestNewCmdVote() { for _, tc := range testCases { tc := tc s.Run(tc.name, func() { - cmd := cli.NewCmdVote() + cmd := cli.NewCmdWeightedVote() clientCtx := val.ClientCtx var txResp sdk.TxResponse diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 374bf24c34b4..46a2c2058d47 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -68,6 +68,7 @@ func NewTxCmd(propCmds []*cobra.Command) *cobra.Command { govTxCmd.AddCommand( NewCmdDeposit(), NewCmdVote(), + NewCmdWeightedVote(), cmdSubmitProp, ) @@ -207,6 +208,60 @@ func NewCmdVote() *cobra.Command { fmt.Sprintf(`Submit a vote for an active proposal. You can find the proposal-id by running "%s query gov proposals". +Example: +$ %s tx gov vote 1 yes --from mykey +`, + version.AppName, version.AppName, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd) + clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags()) + if err != nil { + return err + } + + // Get voting address + from := clientCtx.GetFromAddress() + + // validate that the proposal id is a uint + proposalID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return fmt.Errorf("proposal-id %s not a valid int, please input a valid proposal-id", args[0]) + } + + // Find out which vote option user chose + byteVoteOption, err := types.VoteOptionFromString(govutils.NormalizeVoteOption(args[1])) + if err != nil { + return err + } + + // Build vote message and run basic validation + msg := types.NewMsgVote(from, proposalID, byteVoteOption) + err = msg.ValidateBasic() + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// NewCmdWeightedVote implements creating a new weighted vote command. +func NewCmdWeightedVote() *cobra.Command { + cmd := &cobra.Command{ + Use: "weighted-vote [proposal-id] [weighted-options]", + Args: cobra.ExactArgs(2), + Short: "Vote for an active proposal, options: yes/no/no_with_veto/abstain", + Long: strings.TrimSpace( + fmt.Sprintf(`Submit a vote for an active proposal. You can +find the proposal-id by running "%s query gov proposals". + Example: $ %s tx gov vote 1 yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05 --from mykey `, @@ -236,7 +291,7 @@ $ %s tx gov vote 1 yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05 --from mykey } // Build vote message and run basic validation - msg := types.NewMsgVote(from, proposalID, options) + msg := types.NewMsgWeightedVote(from, proposalID, options) err = msg.ValidateBasic() if err != nil { return err diff --git a/x/gov/client/rest/rest.go b/x/gov/client/rest/rest.go index 6a52179255f1..e7282d8d9a9b 100644 --- a/x/gov/client/rest/rest.go +++ b/x/gov/client/rest/rest.go @@ -52,7 +52,14 @@ type DepositReq struct { // VoteReq defines the properties of a vote request's body. type VoteReq struct { + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + Voter sdk.AccAddress `json:"voter" yaml:"voter"` // address of the voter + Option string `json:"option" yaml:"option"` // option from OptionSet chosen by the voter +} + +// WeightedVoteReq defines the properties of a vote request's body. +type WeightedVoteReq struct { BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` Voter sdk.AccAddress `json:"voter" yaml:"voter"` // address of the voter - Options string `json:"options" yaml:"options"` // option from OptionSet chosen by the voter + Options string `json:"options" yaml:"options"` // weighted options from OptionSet chosen by the voter } diff --git a/x/gov/client/rest/tx.go b/x/gov/client/rest/tx.go index 00c82dd8cc4d..41738269e485 100644 --- a/x/gov/client/rest/tx.go +++ b/x/gov/client/rest/tx.go @@ -22,6 +22,7 @@ func registerTxHandlers(clientCtx client.Context, r *mux.Router, phs []ProposalR r.HandleFunc("/gov/proposals", newPostProposalHandlerFn(clientCtx)).Methods("POST") r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits", RestProposalID), newDepositHandlerFn(clientCtx)).Methods("POST") r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes", RestProposalID), newVoteHandlerFn(clientCtx)).Methods("POST") + r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/weightedvotes", RestProposalID), newWeightedVoteHandlerFn(clientCtx)).Methods("POST") } func newPostProposalHandlerFn(clientCtx client.Context) http.HandlerFunc { @@ -111,14 +112,54 @@ func newVoteHandlerFn(clientCtx client.Context) http.HandlerFunc { return } + voteOption, err := types.VoteOptionFromString(gcutils.NormalizeVoteOption(req.Option)) + if rest.CheckBadRequestError(w, err) { + return + } + + // create the message + msg := types.NewMsgVote(req.Voter, proposalID, voteOption) + if rest.CheckBadRequestError(w, msg.ValidateBasic()) { + return + } + + tx.WriteGeneratedTxResponse(clientCtx, w, req.BaseReq, msg) + } +} + +func newWeightedVoteHandlerFn(clientCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + strProposalID := vars[RestProposalID] + + if len(strProposalID) == 0 { + rest.WriteErrorResponse(w, http.StatusBadRequest, "proposalId required but not specified") + return + } + + proposalID, ok := rest.ParseUint64OrReturnBadRequest(w, strProposalID) + if !ok { + return + } + + var req WeightedVoteReq + if !rest.ReadRESTReq(w, r, clientCtx.LegacyAmino, &req) { + return + } + + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { + return + } + // Figure out which vote options user chose options, err := types.WeightedVoteOptionsFromString(gcutils.NormalizeWeightedVoteOptions(req.Options)) - if err != nil { + if rest.CheckBadRequestError(w, err) { return } // create the message - msg := types.NewMsgVote(req.Voter, proposalID, options) + msg := types.NewMsgWeightedVote(req.Voter, proposalID, options) if rest.CheckBadRequestError(w, msg.ValidateBasic()) { return } diff --git a/x/gov/client/testutil/helpers.go b/x/gov/client/testutil/helpers.go index 535cb8d09ca6..ce9d5de725a5 100644 --- a/x/gov/client/testutil/helpers.go +++ b/x/gov/client/testutil/helpers.go @@ -41,5 +41,5 @@ func MsgVote(clientCtx client.Context, from, id, vote string, extraArgs ...strin args = append(args, extraArgs...) - return clitestutil.ExecTestCLICmd(clientCtx, govcli.NewCmdVote(), args) + return clitestutil.ExecTestCLICmd(clientCtx, govcli.NewCmdWeightedVote(), args) } diff --git a/x/gov/client/utils/query.go b/x/gov/client/utils/query.go index 122d7d2557a0..3f92d6230819 100644 --- a/x/gov/client/utils/query.go +++ b/x/gov/client/utils/query.go @@ -80,6 +80,7 @@ func QueryVotesByTxQuery(clientCtx client.Context, params types.QueryProposalVot var ( events = []string{ fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgVote), + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgWeightedVote), fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), } votes []types.Vote @@ -98,6 +99,14 @@ func QueryVotesByTxQuery(clientCtx client.Context, params types.QueryProposalVot if msg.Type() == types.TypeMsgVote { voteMsg := msg.(*types.MsgVote) + votes = append(votes, types.Vote{ + Voter: voteMsg.Voter, + ProposalId: params.ProposalID, + Options: types.NewNonSplitVoteOption(voteMsg.Option), + }) + } else if msg.Type() == types.TypeMsgWeightedVote { + voteMsg := msg.(*types.MsgWeightedVote) + votes = append(votes, types.Vote{ Voter: voteMsg.Voter, ProposalId: params.ProposalID, @@ -141,23 +150,33 @@ func QueryVoteByTxQuery(clientCtx client.Context, params types.QueryVoteParams) } for _, info := range searchResult.Txs { for _, msg := range info.GetTx().GetMsgs() { + vote := types.Vote{} + // there should only be a single vote under the given conditions if msg.Type() == types.TypeMsgVote { voteMsg := msg.(*types.MsgVote) - vote := types.Vote{ + vote = types.Vote{ Voter: voteMsg.Voter, ProposalId: params.ProposalID, - Options: voteMsg.Options, + Options: types.NewNonSplitVoteOption(voteMsg.Option), } + } else if msg.Type() == types.TypeMsgWeightedVote { + voteMsg := msg.(*types.MsgWeightedVote) - bz, err := clientCtx.JSONMarshaler.MarshalJSON(&vote) - if err != nil { - return nil, err + vote = types.Vote{ + Voter: voteMsg.Voter, + ProposalId: params.ProposalID, + Options: voteMsg.Options, } + } - return bz, nil + bz, err := clientCtx.JSONMarshaler.MarshalJSON(&vote) + if err != nil { + return nil, err } + + return bz, nil } } diff --git a/x/gov/client/utils/query_test.go b/x/gov/client/utils/query_test.go index 90d3e96c7a8b..8ad99b2c1797 100644 --- a/x/gov/client/utils/query_test.go +++ b/x/gov/client/utils/query_test.go @@ -70,12 +70,12 @@ func TestGetPaginatedVotes(t *testing.T) { acc2 := make(sdk.AccAddress, 20) acc2[0] = 2 acc1Msgs := []sdk.Msg{ - types.NewMsgVote(acc1, 0, types.NewNonSplitVoteOption(types.OptionYes)), - types.NewMsgVote(acc1, 0, types.NewNonSplitVoteOption(types.OptionYes)), + types.NewMsgVote(acc1, 0, types.OptionYes), + types.NewMsgVote(acc1, 0, types.OptionYes), } acc2Msgs := []sdk.Msg{ - types.NewMsgVote(acc2, 0, types.NewNonSplitVoteOption(types.OptionYes)), - types.NewMsgVote(acc2, 0, types.NewNonSplitVoteOption(types.OptionYes)), + types.NewMsgVote(acc2, 0, types.OptionYes), + types.NewMsgWeightedVote(acc2, 0, types.NewNonSplitVoteOption(types.OptionYes)), } for _, tc := range []testCase{ { diff --git a/x/gov/handler.go b/x/gov/handler.go index 25d97bfabb47..61258e81396c 100644 --- a/x/gov/handler.go +++ b/x/gov/handler.go @@ -27,6 +27,10 @@ func NewHandler(k keeper.Keeper) sdk.Handler { res, err := msgServer.Vote(sdk.WrapSDKContext(ctx), msg) return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgWeightedVote: + res, err := msgServer.WeightedVote(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) + default: return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", types.ModuleName, msg) } diff --git a/x/gov/keeper/msg_server.go b/x/gov/keeper/msg_server.go index aa92591ab9ce..3d02ae95e8b4 100644 --- a/x/gov/keeper/msg_server.go +++ b/x/gov/keeper/msg_server.go @@ -59,6 +59,36 @@ func (k msgServer) SubmitProposal(goCtx context.Context, msg *types.MsgSubmitPro } func (k msgServer) Vote(goCtx context.Context, msg *types.MsgVote) (*types.MsgVoteResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + accAddr, accErr := sdk.AccAddressFromBech32(msg.Voter) + if accErr != nil { + return nil, accErr + } + err := k.Keeper.AddVote(ctx, msg.ProposalId, accAddr, types.NewNonSplitVoteOption(msg.Option)) + if err != nil { + return nil, err + } + + defer telemetry.IncrCounterWithLabels( + []string{types.ModuleName, "vote"}, + 1, + []metrics.Label{ + telemetry.NewLabel("proposal_id", strconv.Itoa(int(msg.ProposalId))), + }, + ) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Voter), + ), + ) + + return &types.MsgVoteResponse{}, nil +} + +func (k msgServer) WeightedVote(goCtx context.Context, msg *types.MsgWeightedVote) (*types.MsgVoteResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) accAddr, accErr := sdk.AccAddressFromBech32(msg.Voter) if accErr != nil { diff --git a/x/gov/simulation/operations.go b/x/gov/simulation/operations.go index 29196a20c3c6..88b82bf3f1eb 100644 --- a/x/gov/simulation/operations.go +++ b/x/gov/simulation/operations.go @@ -20,8 +20,9 @@ var initialProposalID = uint64(100000000000000) // Simulation operation weights constants const ( - OpWeightMsgDeposit = "op_weight_msg_deposit" - OpWeightMsgVote = "op_weight_msg_vote" + OpWeightMsgDeposit = "op_weight_msg_deposit" + OpWeightMsgVote = "op_weight_msg_vote" + OpWeightMsgWeightedVote = "op_weight_msg_weighted_vote" ) // WeightedOperations returns all the operations from the module with their respective weights @@ -31,8 +32,9 @@ func WeightedOperations( ) simulation.WeightedOperations { var ( - weightMsgDeposit int - weightMsgVote int + weightMsgDeposit int + weightMsgVote int + weightMsgWeightedVote int ) appParams.GetOrGenerate(cdc, OpWeightMsgDeposit, &weightMsgDeposit, nil, @@ -47,6 +49,12 @@ func WeightedOperations( }, ) + appParams.GetOrGenerate(cdc, OpWeightMsgWeightedVote, &weightMsgWeightedVote, nil, + func(_ *rand.Rand) { + weightMsgWeightedVote = simappparams.DefaultWeightMsgWeightedVote + }, + ) + // generate the weighted operations for the proposal contents var wProposalOps simulation.WeightedOperations @@ -74,12 +82,16 @@ func WeightedOperations( weightMsgVote, SimulateMsgVote(ak, bk, k), ), + simulation.NewWeightedOperation( + weightMsgWeightedVote, + SimulateMsgWeightedVote(ak, bk, k), + ), } return append(wProposalOps, wGovOps...) } -// SimulateSubmitProposal simulates creating a msg Submit Proposal +// SimulateMsgSubmitProposal simulates creating a msg Submit Proposal // voting on the proposal, and subsequently slashing the proposal. It is implemented using // future operations. func SimulateMsgSubmitProposal( @@ -281,7 +293,70 @@ func operationSimulateMsgVote(ak types.AccountKeeper, bk types.BankKeeper, k kee } option := randomVotingOption(r) - msg := types.NewMsgVote(simAccount.Address, proposalID, types.NewNonSplitVoteOption(option)) + msg := types.NewMsgVote(simAccount.Address, proposalID, option) + + account := ak.GetAccount(ctx, simAccount.Address) + spendable := bk.SpendableCoins(ctx, account.GetAddress()) + + fees, err := simtypes.RandomFees(r, ctx, spendable) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to generate fees"), nil, err + } + + txGen := simappparams.MakeEncodingConfig().TxConfig + tx, err := helpers.GenTx( + txGen, + []sdk.Msg{msg}, + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + simAccount.PrivKey, + ) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err + } + + return simtypes.NewOperationMsg(msg, true, ""), nil, nil + } +} + +// SimulateMsgWeightedVote generates a MsgWeightedVote with random values. +func SimulateMsgWeightedVote(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { + return operationSimulateMsgWeightedVote(ak, bk, k, simtypes.Account{}, -1) +} + +func operationSimulateMsgWeightedVote(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, + simAccount simtypes.Account, proposalIDInt int64) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + if simAccount.Equals(simtypes.Account{}) { + simAccount, _ = simtypes.RandomAcc(r, accs) + } + + var proposalID uint64 + + switch { + case proposalIDInt < 0: + var ok bool + proposalID, ok = randomProposalID(r, k, ctx, types.StatusVotingPeriod) + if !ok { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgWeightedVote, "unable to generate proposalID"), nil, nil + } + default: + proposalID = uint64(proposalIDInt) + } + + options := randomWeightedVotingOptions(r) + msg := types.NewMsgWeightedVote(simAccount.Address, proposalID, options) account := ak.GetAccount(ctx, simAccount.Address) spendable := bk.SpendableCoins(ctx, account.GetAddress()) @@ -393,3 +468,37 @@ func randomVotingOption(r *rand.Rand) types.VoteOption { panic("invalid vote option") } } + +// Pick a random weighted voting options +func randomWeightedVotingOptions(r *rand.Rand) types.WeightedVoteOptions { + w1 := r.Intn(100 + 1) + w2 := r.Intn(100 - w1 + 1) + w3 := r.Intn(100 - w1 - w2 + 1) + w4 := 100 - w1 - w2 - w3 + weightedVoteOptions := types.WeightedVoteOptions{} + if w1 > 0 { + weightedVoteOptions = append(weightedVoteOptions, types.WeightedVoteOption{ + Option: types.OptionYes, + Weight: sdk.NewDecWithPrec(int64(w1), 2), + }) + } + if w2 > 0 { + weightedVoteOptions = append(weightedVoteOptions, types.WeightedVoteOption{ + Option: types.OptionAbstain, + Weight: sdk.NewDecWithPrec(int64(w2), 2), + }) + } + if w3 > 0 { + weightedVoteOptions = append(weightedVoteOptions, types.WeightedVoteOption{ + Option: types.OptionNo, + Weight: sdk.NewDecWithPrec(int64(w3), 2), + }) + } + if w4 > 0 { + weightedVoteOptions = append(weightedVoteOptions, types.WeightedVoteOption{ + Option: types.OptionNoWithVeto, + Weight: sdk.NewDecWithPrec(int64(w4), 2), + }) + } + return weightedVoteOptions +} diff --git a/x/gov/simulation/operations_test.go b/x/gov/simulation/operations_test.go index 83197a585488..52217ad74fc4 100644 --- a/x/gov/simulation/operations_test.go +++ b/x/gov/simulation/operations_test.go @@ -80,6 +80,7 @@ func TestWeightedOperations(t *testing.T) { {2, types.ModuleName, "submit_proposal"}, {simappparams.DefaultWeightMsgDeposit, types.ModuleName, types.TypeMsgDeposit}, {simappparams.DefaultWeightMsgVote, types.ModuleName, types.TypeMsgVote}, + {simappparams.DefaultWeightMsgWeightedVote, types.ModuleName, types.TypeMsgWeightedVote}, } for i, w := range weightesOps { @@ -202,11 +203,51 @@ func TestSimulateMsgVote(t *testing.T) { require.True(t, operationMsg.OK) require.Equal(t, uint64(1), msg.ProposalId) require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Voter) - require.True(t, len(msg.Options) == 1) - require.Equal(t, types.OptionYes, msg.Options[0].Option) + require.Equal(t, types.OptionYes, msg.Option) require.Equal(t, "gov", msg.Route()) require.Equal(t, types.TypeMsgVote, msg.Type()) +} + +// TestSimulateMsgWeightedVote tests the normal scenario of a valid message of type TypeMsgWeightedVote. +// Abonormal scenarios, where the message is created by an errors are not tested here. +func TestSimulateMsgWeightedVote(t *testing.T) { + app, ctx := createTestApp(false) + blockTime := time.Now().UTC() + ctx = ctx.WithBlockTime(blockTime) + + // setup 3 accounts + s := rand.NewSource(1) + r := rand.New(s) + accounts := getTestingAccounts(t, r, app, ctx, 3) + + // setup a proposal + content := types.NewTextProposal("Test", "description") + submitTime := ctx.BlockHeader().Time + depositPeriod := app.GovKeeper.GetDepositParams(ctx).MaxDepositPeriod + + proposal, err := types.NewProposal(content, 1, submitTime, submitTime.Add(depositPeriod)) + require.NoError(t, err) + + app.GovKeeper.ActivateVotingPeriod(ctx, proposal) + + // begin a new block + app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: app.LastBlockHeight() + 1, AppHash: app.LastCommitID().Hash, Time: blockTime}}) + + // execute operation + op := simulation.SimulateMsgWeightedVote(app.AccountKeeper, app.BankKeeper, app.GovKeeper) + operationMsg, _, err := op(r, app.BaseApp, ctx, accounts, "") + require.NoError(t, err) + + var msg types.MsgWeightedVote + types.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + + require.True(t, operationMsg.OK) + require.Equal(t, uint64(1), msg.ProposalId) + require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Voter) + require.True(t, len(msg.Options) >= 1) + require.Equal(t, "gov", msg.Route()) + require.Equal(t, types.TypeMsgWeightedVote, msg.Type()) } // returns context and an app with updated mint keeper diff --git a/x/gov/spec/04_events.md b/x/gov/spec/04_events.md index dc3b1bf3a231..1ea2a36b7613 100644 --- a/x/gov/spec/04_events.md +++ b/x/gov/spec/04_events.md @@ -41,6 +41,16 @@ The governance module emits the following events: | message | action | vote | | message | sender | {senderAddress} | +### MsgWeightedVote + +| Type | Attribute Key | Attribute Value | +| ------------- | ------------- | ------------------------ | +| proposal_vote | option | {weightedVoteOptions} | +| proposal_vote | proposal_id | {proposalID} | +| message | module | governance | +| message | action | vote | +| message | sender | {senderAddress} | + ### MsgDeposit | Type | Attribute Key | Attribute Value | diff --git a/x/gov/types/codec.go b/x/gov/types/codec.go index 85bac043abdd..735733e357b5 100644 --- a/x/gov/types/codec.go +++ b/x/gov/types/codec.go @@ -14,6 +14,7 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgSubmitProposal{}, "cosmos-sdk/MsgSubmitProposal", nil) cdc.RegisterConcrete(&MsgDeposit{}, "cosmos-sdk/MsgDeposit", nil) cdc.RegisterConcrete(&MsgVote{}, "cosmos-sdk/MsgVote", nil) + cdc.RegisterConcrete(&MsgWeightedVote{}, "cosmos-sdk/MsgWeightedVote", nil) cdc.RegisterConcrete(&TextProposal{}, "cosmos-sdk/TextProposal", nil) } @@ -21,6 +22,7 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), &MsgSubmitProposal{}, &MsgVote{}, + &MsgWeightedVote{}, &MsgDeposit{}, ) registry.RegisterInterface( diff --git a/x/gov/types/msgs.go b/x/gov/types/msgs.go index 2cb3db539581..4c8d47d7c0f0 100644 --- a/x/gov/types/msgs.go +++ b/x/gov/types/msgs.go @@ -16,12 +16,13 @@ import ( const ( TypeMsgDeposit = "deposit" TypeMsgVote = "vote" + TypeMsgWeightedVote = "weighted_vote" TypeMsgSubmitProposal = "submit_proposal" ) var ( - _, _, _ sdk.Msg = &MsgSubmitProposal{}, &MsgDeposit{}, &MsgVote{} - _ types.UnpackInterfacesMessage = &MsgSubmitProposal{} + _, _, _, _ sdk.Msg = &MsgSubmitProposal{}, &MsgDeposit{}, &MsgVote{}, &MsgWeightedVote{} + _ types.UnpackInterfacesMessage = &MsgSubmitProposal{} ) // NewMsgSubmitProposal creates a new MsgSubmitProposal. @@ -177,8 +178,8 @@ func (msg MsgDeposit) GetSigners() []sdk.AccAddress { // NewMsgVote creates a message to cast a vote on an active proposal //nolint:interfacer -func NewMsgVote(voter sdk.AccAddress, proposalID uint64, options WeightedVoteOptions) *MsgVote { - return &MsgVote{proposalID, voter.String(), options} +func NewMsgVote(voter sdk.AccAddress, proposalID uint64, option VoteOption) *MsgVote { + return &MsgVote{proposalID, voter.String(), option} } // Route implements Msg @@ -193,6 +194,49 @@ func (msg MsgVote) ValidateBasic() error { return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Voter) } + if !ValidVoteOption(msg.Option) { + return sdkerrors.Wrap(ErrInvalidVote, msg.Option.String()) + } + + return nil +} + +// String implements the Stringer interface +func (msg MsgVote) String() string { + out, _ := yaml.Marshal(msg) + return string(out) +} + +// GetSignBytes implements Msg +func (msg MsgVote) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(&msg) + return sdk.MustSortJSON(bz) +} + +// GetSigners implements Msg +func (msg MsgVote) GetSigners() []sdk.AccAddress { + voter, _ := sdk.AccAddressFromBech32(msg.Voter) + return []sdk.AccAddress{voter} +} + +// NewMsgWeightedVote creates a message to cast a vote on an active proposal +//nolint:interfacer +func NewMsgWeightedVote(voter sdk.AccAddress, proposalID uint64, options WeightedVoteOptions) *MsgWeightedVote { + return &MsgWeightedVote{proposalID, voter.String(), options} +} + +// Route implements Msg +func (msg MsgWeightedVote) Route() string { return RouterKey } + +// Type implements Msg +func (msg MsgWeightedVote) Type() string { return TypeMsgWeightedVote } + +// ValidateBasic implements Msg +func (msg MsgWeightedVote) ValidateBasic() error { + if msg.Voter == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Voter) + } + if len(msg.Options) == 0 { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, WeightedVoteOptions(msg.Options).String()) } @@ -218,19 +262,19 @@ func (msg MsgVote) ValidateBasic() error { } // String implements the Stringer interface -func (msg MsgVote) String() string { +func (msg MsgWeightedVote) String() string { out, _ := yaml.Marshal(msg) return string(out) } // GetSignBytes implements Msg -func (msg MsgVote) GetSignBytes() []byte { +func (msg MsgWeightedVote) GetSignBytes() []byte { bz := ModuleCdc.MustMarshalJSON(&msg) return sdk.MustSortJSON(bz) } // GetSigners implements Msg -func (msg MsgVote) GetSigners() []sdk.AccAddress { +func (msg MsgWeightedVote) GetSigners() []sdk.AccAddress { voter, _ := sdk.AccAddressFromBech32(msg.Voter) return []sdk.AccAddress{voter} } diff --git a/x/gov/types/msgs_test.go b/x/gov/types/msgs_test.go index c457c564fed1..a1e1accba022 100644 --- a/x/gov/types/msgs_test.go +++ b/x/gov/types/msgs_test.go @@ -92,8 +92,34 @@ func TestMsgDeposit(t *testing.T) { } } -// test ValidateBasic for MsgDeposit +// test ValidateBasic for MsgVote func TestMsgVote(t *testing.T) { + tests := []struct { + proposalID uint64 + voterAddr sdk.AccAddress + option VoteOption + expectPass bool + }{ + {0, addrs[0], OptionYes, true}, + {0, sdk.AccAddress{}, OptionYes, false}, + {0, addrs[0], OptionNo, true}, + {0, addrs[0], OptionNoWithVeto, true}, + {0, addrs[0], OptionAbstain, true}, + {0, addrs[0], VoteOption(0x13), false}, + } + + for i, tc := range tests { + msg := NewMsgVote(tc.voterAddr, tc.proposalID, tc.option) + if tc.expectPass { + require.Nil(t, msg.ValidateBasic(), "test: %v", i) + } else { + require.NotNil(t, msg.ValidateBasic(), "test: %v", i) + } + } +} + +// test ValidateBasic for MsgWeightedVote +func TestMsgWeightedVote(t *testing.T) { tests := []struct { proposalID uint64 voterAddr sdk.AccAddress @@ -124,7 +150,7 @@ func TestMsgVote(t *testing.T) { } for i, tc := range tests { - msg := NewMsgVote(tc.voterAddr, tc.proposalID, tc.options) + msg := NewMsgWeightedVote(tc.voterAddr, tc.proposalID, tc.options) if tc.expectPass { require.Nil(t, msg.ValidateBasic(), "test: %v", i) } else { diff --git a/x/gov/types/tx.pb.go b/x/gov/types/tx.pb.go index d77104ae7037..71222492cf19 100644 --- a/x/gov/types/tx.pb.go +++ b/x/gov/types/tx.pb.go @@ -119,9 +119,9 @@ func (m *MsgSubmitProposalResponse) GetProposalId() uint64 { // MsgVote defines a message to cast a vote. type MsgVote struct { - ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id" yaml:"proposal_id"` - Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` - Options []WeightedVoteOption `protobuf:"bytes,3,rep,name=options,proto3" json:"options"` + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty" yaml:"proposal_id"` + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` + Option VoteOption `protobuf:"varint,3,opt,name=option,proto3,enum=cosmos.gov.v1beta1.VoteOption" json:"option,omitempty"` } func (m *MsgVote) Reset() { *m = MsgVote{} } @@ -156,6 +156,45 @@ func (m *MsgVote) XXX_DiscardUnknown() { var xxx_messageInfo_MsgVote proto.InternalMessageInfo +// MsgVote defines a message to cast a vote. +type MsgWeightedVote struct { + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id" yaml:"proposal_id"` + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` + Options []WeightedVoteOption `protobuf:"bytes,3,rep,name=options,proto3" json:"options"` +} + +func (m *MsgWeightedVote) Reset() { *m = MsgWeightedVote{} } +func (*MsgWeightedVote) ProtoMessage() {} +func (*MsgWeightedVote) Descriptor() ([]byte, []int) { + return fileDescriptor_3c053992595e3dce, []int{3} +} +func (m *MsgWeightedVote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgWeightedVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgWeightedVote.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 *MsgWeightedVote) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgWeightedVote.Merge(m, src) +} +func (m *MsgWeightedVote) XXX_Size() int { + return m.Size() +} +func (m *MsgWeightedVote) XXX_DiscardUnknown() { + xxx_messageInfo_MsgWeightedVote.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgWeightedVote proto.InternalMessageInfo + // MsgVoteResponse defines the Msg/Vote response type. type MsgVoteResponse struct { } @@ -164,7 +203,7 @@ func (m *MsgVoteResponse) Reset() { *m = MsgVoteResponse{} } func (m *MsgVoteResponse) String() string { return proto.CompactTextString(m) } func (*MsgVoteResponse) ProtoMessage() {} func (*MsgVoteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_3c053992595e3dce, []int{3} + return fileDescriptor_3c053992595e3dce, []int{4} } func (m *MsgVoteResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -203,7 +242,7 @@ type MsgDeposit struct { func (m *MsgDeposit) Reset() { *m = MsgDeposit{} } func (*MsgDeposit) ProtoMessage() {} func (*MsgDeposit) Descriptor() ([]byte, []int) { - return fileDescriptor_3c053992595e3dce, []int{4} + return fileDescriptor_3c053992595e3dce, []int{5} } func (m *MsgDeposit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -240,7 +279,7 @@ func (m *MsgDepositResponse) Reset() { *m = MsgDepositResponse{} } func (m *MsgDepositResponse) String() string { return proto.CompactTextString(m) } func (*MsgDepositResponse) ProtoMessage() {} func (*MsgDepositResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_3c053992595e3dce, []int{5} + return fileDescriptor_3c053992595e3dce, []int{6} } func (m *MsgDepositResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -273,6 +312,7 @@ func init() { proto.RegisterType((*MsgSubmitProposal)(nil), "cosmos.gov.v1beta1.MsgSubmitProposal") proto.RegisterType((*MsgSubmitProposalResponse)(nil), "cosmos.gov.v1beta1.MsgSubmitProposalResponse") proto.RegisterType((*MsgVote)(nil), "cosmos.gov.v1beta1.MsgVote") + proto.RegisterType((*MsgWeightedVote)(nil), "cosmos.gov.v1beta1.MsgWeightedVote") proto.RegisterType((*MsgVoteResponse)(nil), "cosmos.gov.v1beta1.MsgVoteResponse") proto.RegisterType((*MsgDeposit)(nil), "cosmos.gov.v1beta1.MsgDeposit") proto.RegisterType((*MsgDepositResponse)(nil), "cosmos.gov.v1beta1.MsgDepositResponse") @@ -281,45 +321,48 @@ func init() { func init() { proto.RegisterFile("cosmos/gov/v1beta1/tx.proto", fileDescriptor_3c053992595e3dce) } var fileDescriptor_3c053992595e3dce = []byte{ - // 596 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x3d, 0x6f, 0xd3, 0x50, - 0x14, 0xb5, 0x93, 0xd2, 0xd0, 0x17, 0xa9, 0xa5, 0x4f, 0x11, 0x4a, 0xd3, 0xca, 0x8e, 0x8c, 0x5a, - 0x65, 0xa9, 0x4d, 0xcb, 0x56, 0x26, 0x5c, 0x54, 0x01, 0x52, 0x04, 0x18, 0x09, 0x24, 0x96, 0xca, - 0x76, 0x5e, 0x5f, 0x2d, 0x12, 0x5f, 0x2b, 0xef, 0x25, 0x6a, 0x36, 0x46, 0xc4, 0x00, 0x8c, 0x8c, - 0x9d, 0x99, 0xf9, 0x03, 0x6c, 0x15, 0x53, 0x47, 0x06, 0x14, 0x50, 0xbb, 0x00, 0x63, 0x7f, 0x01, - 0xf2, 0xfb, 0x48, 0xab, 0x36, 0x8d, 0x40, 0xea, 0x94, 0xdc, 0x7b, 0xee, 0x39, 0xf2, 0x39, 0xf7, - 0xda, 0x68, 0x31, 0x06, 0xd6, 0x01, 0xe6, 0x51, 0xe8, 0x7b, 0xfd, 0xb5, 0x88, 0xf0, 0x70, 0xcd, - 0xe3, 0x7b, 0x6e, 0xd6, 0x05, 0x0e, 0x18, 0x4b, 0xd0, 0xa5, 0xd0, 0x77, 0x15, 0x58, 0xb3, 0x14, - 0x21, 0x0a, 0x19, 0x19, 0x31, 0x62, 0x48, 0x52, 0xc9, 0xa9, 0x2d, 0x8d, 0x11, 0xcc, 0xf9, 0x12, - 0x5d, 0x90, 0xe8, 0xb6, 0xa8, 0x3c, 0x25, 0x2f, 0xa1, 0x0a, 0x05, 0x0a, 0xb2, 0x9f, 0xff, 0xd3, - 0x04, 0x0a, 0x40, 0xdb, 0xc4, 0x13, 0x55, 0xd4, 0xdb, 0xf1, 0xc2, 0x74, 0x20, 0x21, 0xe7, 0x7d, - 0x01, 0xcd, 0x37, 0x19, 0x7d, 0xd6, 0x8b, 0x3a, 0x09, 0x7f, 0xd2, 0x85, 0x0c, 0x58, 0xd8, 0xc6, - 0x77, 0x51, 0x29, 0x86, 0x94, 0x93, 0x94, 0x57, 0xcd, 0xba, 0xd9, 0x28, 0xaf, 0x57, 0x5c, 0x29, - 0xe1, 0x6a, 0x09, 0xf7, 0x5e, 0x3a, 0xf0, 0xcb, 0x5f, 0x3f, 0xaf, 0x96, 0x36, 0xe5, 0x60, 0xa0, - 0x19, 0xf8, 0x9d, 0x89, 0xe6, 0x92, 0x34, 0xe1, 0x49, 0xd8, 0xde, 0x6e, 0x91, 0x0c, 0x58, 0xc2, - 0xab, 0x85, 0x7a, 0xb1, 0x51, 0x5e, 0x5f, 0x70, 0xd5, 0xc3, 0xe6, 0xbe, 0x75, 0x18, 0xee, 0x26, - 0x24, 0xa9, 0xff, 0xe8, 0x60, 0x68, 0x1b, 0x27, 0x43, 0xfb, 0xe6, 0x20, 0xec, 0xb4, 0x37, 0x9c, - 0x73, 0x7c, 0xe7, 0xd3, 0x0f, 0xbb, 0x41, 0x13, 0xbe, 0xdb, 0x8b, 0xdc, 0x18, 0x3a, 0xca, 0xb3, - 0xfa, 0x59, 0x65, 0xad, 0x57, 0x1e, 0x1f, 0x64, 0x84, 0x09, 0x29, 0x16, 0xcc, 0x2a, 0xf6, 0x7d, - 0x49, 0xc6, 0x35, 0x74, 0x3d, 0x13, 0xce, 0x48, 0xb7, 0x5a, 0xac, 0x9b, 0x8d, 0x99, 0x60, 0x54, - 0x6f, 0xdc, 0x78, 0xb3, 0x6f, 0x1b, 0x1f, 0xf7, 0x6d, 0xe3, 0xd7, 0xbe, 0x6d, 0xbc, 0xfe, 0x5e, - 0x37, 0x9c, 0x18, 0x2d, 0x5c, 0x08, 0x24, 0x20, 0x2c, 0x83, 0x94, 0x11, 0xbc, 0x85, 0xca, 0x99, - 0xea, 0x6d, 0x27, 0x2d, 0x11, 0xce, 0x94, 0xbf, 0xfc, 0x67, 0x68, 0x9f, 0x6d, 0x9f, 0x0c, 0x6d, - 0x2c, 0x6d, 0x9c, 0x69, 0x3a, 0x01, 0xd2, 0xd5, 0xc3, 0x96, 0xf3, 0xc5, 0x44, 0xa5, 0x26, 0xa3, - 0xcf, 0x81, 0x5f, 0x99, 0x26, 0xae, 0xa0, 0x6b, 0x7d, 0xe0, 0xa4, 0x5b, 0x2d, 0x08, 0x8f, 0xb2, - 0xc0, 0x5b, 0xa8, 0x04, 0x19, 0x4f, 0x20, 0x65, 0xd5, 0xa2, 0x58, 0xc2, 0x8a, 0x7b, 0xf1, 0x20, - 0xdd, 0x17, 0x24, 0xa1, 0xbb, 0x9c, 0xb4, 0xf2, 0x07, 0x7a, 0x2c, 0xc6, 0xfd, 0xa9, 0x7c, 0x23, - 0x81, 0x26, 0x8f, 0x09, 0x6a, 0x1e, 0xcd, 0x29, 0x0b, 0x3a, 0x1e, 0xe7, 0xb7, 0x89, 0x50, 0x93, - 0x51, 0x1d, 0xfc, 0x55, 0x39, 0x5b, 0x42, 0x33, 0xea, 0x10, 0x40, 0xbb, 0x3b, 0x6d, 0xe0, 0x18, - 0x4d, 0x87, 0x1d, 0xe8, 0xa5, 0x5c, 0x19, 0x9c, 0x70, 0x65, 0xb7, 0x73, 0x4f, 0xff, 0x75, 0x4b, - 0x4a, 0x7a, 0x8c, 0xfd, 0x0a, 0xc2, 0xa7, 0x56, 0x75, 0x02, 0xeb, 0x6f, 0x0b, 0xa8, 0xd8, 0x64, - 0x14, 0xef, 0xa0, 0xd9, 0x73, 0xef, 0xd4, 0xf2, 0xb8, 0xdc, 0x2f, 0x5c, 0x5a, 0x6d, 0xf5, 0x9f, - 0xc6, 0x46, 0x07, 0xf9, 0x00, 0x4d, 0x89, 0x23, 0x5a, 0xbc, 0x84, 0x96, 0x83, 0xb5, 0x5b, 0x13, - 0xc0, 0x91, 0xd2, 0x53, 0x54, 0xd2, 0x7b, 0xb3, 0x2e, 0x99, 0x57, 0x78, 0x6d, 0x65, 0x32, 0xae, - 0x25, 0x7d, 0xff, 0xe0, 0xc8, 0x32, 0x0f, 0x8f, 0x2c, 0xf3, 0xe7, 0x91, 0x65, 0x7e, 0x38, 0xb6, - 0x8c, 0xc3, 0x63, 0xcb, 0xf8, 0x76, 0x6c, 0x19, 0x2f, 0x27, 0x2f, 0x60, 0x4f, 0x7c, 0xf8, 0xc4, - 0x1a, 0xa2, 0x69, 0xf1, 0xc5, 0xb9, 0xf3, 0x37, 0x00, 0x00, 0xff, 0xff, 0xb6, 0x98, 0x0c, 0x31, - 0x64, 0x05, 0x00, 0x00, + // 652 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xb1, 0x6f, 0xd3, 0x4e, + 0x14, 0xb6, 0x93, 0xfe, 0x9a, 0x5f, 0x2f, 0xa8, 0xa5, 0xa7, 0xa8, 0x4a, 0xd3, 0xca, 0x8e, 0x8c, + 0x5a, 0x65, 0xa9, 0x4d, 0x83, 0x04, 0x52, 0x99, 0x48, 0x51, 0x05, 0x48, 0x11, 0x60, 0x24, 0x40, + 0x2c, 0x95, 0x93, 0x5c, 0xaf, 0x16, 0x89, 0x9f, 0x95, 0xbb, 0x44, 0xcd, 0xc6, 0xc8, 0x04, 0x8c, + 0x8c, 0x15, 0x23, 0x33, 0x7f, 0x44, 0x61, 0xea, 0xc8, 0x80, 0x02, 0x6a, 0x19, 0x80, 0xb1, 0x7f, + 0x01, 0xf2, 0xdd, 0x39, 0x0d, 0x8d, 0x13, 0x8a, 0xd4, 0x29, 0x79, 0xef, 0x7b, 0xdf, 0xe7, 0xf7, + 0xbd, 0x7b, 0x77, 0x68, 0xa9, 0x0e, 0xac, 0x05, 0xcc, 0xa1, 0xd0, 0x75, 0xba, 0xeb, 0x35, 0xc2, + 0xbd, 0x75, 0x87, 0xef, 0xd9, 0x61, 0x1b, 0x38, 0x60, 0x2c, 0x41, 0x9b, 0x42, 0xd7, 0x56, 0x60, + 0xc1, 0x50, 0x84, 0x9a, 0xc7, 0xc8, 0x80, 0x51, 0x07, 0x3f, 0x90, 0x9c, 0xc2, 0x72, 0x82, 0x60, + 0xc4, 0x97, 0xe8, 0xa2, 0x44, 0xb7, 0x45, 0xe4, 0x28, 0x79, 0x09, 0xe5, 0x28, 0x50, 0x90, 0xf9, + 0xe8, 0x5f, 0x4c, 0xa0, 0x00, 0xb4, 0x49, 0x1c, 0x11, 0xd5, 0x3a, 0x3b, 0x8e, 0x17, 0xf4, 0x24, + 0x64, 0xbd, 0x4e, 0xa1, 0xf9, 0x2a, 0xa3, 0x8f, 0x3a, 0xb5, 0x96, 0xcf, 0x1f, 0xb4, 0x21, 0x04, + 0xe6, 0x35, 0xf1, 0x4d, 0x94, 0xa9, 0x43, 0xc0, 0x49, 0xc0, 0xf3, 0x7a, 0x51, 0x2f, 0x65, 0xcb, + 0x39, 0x5b, 0x4a, 0xd8, 0xb1, 0x84, 0x7d, 0x2b, 0xe8, 0x55, 0xb2, 0x9f, 0x3e, 0xac, 0x65, 0x36, + 0x65, 0xa1, 0x1b, 0x33, 0xf0, 0x2b, 0x1d, 0xcd, 0xf9, 0x81, 0xcf, 0x7d, 0xaf, 0xb9, 0xdd, 0x20, + 0x21, 0x30, 0x9f, 0xe7, 0x53, 0xc5, 0x74, 0x29, 0x5b, 0x5e, 0xb4, 0x55, 0xb3, 0x91, 0xef, 0x78, + 0x18, 0xf6, 0x26, 0xf8, 0x41, 0xe5, 0xde, 0x41, 0xdf, 0xd4, 0x4e, 0xfa, 0xe6, 0x42, 0xcf, 0x6b, + 0x35, 0x37, 0xac, 0x33, 0x7c, 0xeb, 0xfd, 0x57, 0xb3, 0x44, 0x7d, 0xbe, 0xdb, 0xa9, 0xd9, 0x75, + 0x68, 0x29, 0xcf, 0xea, 0x67, 0x8d, 0x35, 0x9e, 0x3b, 0xbc, 0x17, 0x12, 0x26, 0xa4, 0x98, 0x3b, + 0xab, 0xd8, 0xb7, 0x25, 0x19, 0x17, 0xd0, 0xff, 0xa1, 0x70, 0x46, 0xda, 0xf9, 0x74, 0x51, 0x2f, + 0xcd, 0xb8, 0x83, 0x78, 0xe3, 0xf2, 0xcb, 0x7d, 0x53, 0x7b, 0xbb, 0x6f, 0x6a, 0x3f, 0xf6, 0x4d, + 0xed, 0xc5, 0x97, 0xa2, 0x66, 0xd5, 0xd1, 0xe2, 0xc8, 0x40, 0x5c, 0xc2, 0x42, 0x08, 0x18, 0xc1, + 0x5b, 0x28, 0x1b, 0xaa, 0xdc, 0xb6, 0xdf, 0x10, 0xc3, 0x99, 0xaa, 0xac, 0xfc, 0xea, 0x9b, 0xc3, + 0xe9, 0x93, 0xbe, 0x89, 0xa5, 0x8d, 0xa1, 0xa4, 0xe5, 0xa2, 0x38, 0xba, 0xdb, 0xb0, 0xde, 0xe9, + 0x28, 0x53, 0x65, 0xf4, 0x31, 0x70, 0x82, 0x6f, 0x24, 0x69, 0x2e, 0xfc, 0x5d, 0x04, 0xe7, 0xd0, + 0x7f, 0x5d, 0xe0, 0xa4, 0x9d, 0x4f, 0x09, 0x53, 0x32, 0xc0, 0xd7, 0xd1, 0x34, 0x84, 0xdc, 0x87, + 0x40, 0x78, 0x9d, 0x2d, 0x1b, 0xf6, 0xe8, 0x02, 0xda, 0xd1, 0x87, 0xef, 0x8b, 0x2a, 0x57, 0x55, + 0x27, 0x4c, 0xe2, 0xa3, 0x8e, 0xe6, 0xaa, 0x8c, 0x3e, 0x21, 0x3e, 0xdd, 0xe5, 0xa4, 0x21, 0x9a, + 0xbd, 0xa0, 0x01, 0x8c, 0xe9, 0x7d, 0x0b, 0x65, 0x64, 0x37, 0x2c, 0x9f, 0x16, 0x1b, 0xb3, 0x9a, + 0xd4, 0xfc, 0x70, 0x43, 0xd2, 0x44, 0x65, 0x2a, 0x5a, 0x1f, 0x37, 0x26, 0x27, 0x78, 0x99, 0x17, + 0x56, 0x22, 0x46, 0x7c, 0x96, 0xd6, 0x4f, 0x1d, 0xa1, 0x2a, 0xa3, 0xf1, 0x96, 0x5c, 0x94, 0xb3, + 0x65, 0x34, 0xa3, 0xb6, 0x16, 0x62, 0x77, 0xa7, 0x09, 0x5c, 0x47, 0xd3, 0x5e, 0x0b, 0x3a, 0x01, + 0x57, 0x06, 0x27, 0x5c, 0x89, 0xab, 0x91, 0xa7, 0x7f, 0x5a, 0x7c, 0x25, 0x9d, 0x60, 0x3f, 0x87, + 0xf0, 0xa9, 0xd5, 0x78, 0x02, 0xe5, 0xef, 0x29, 0x94, 0xae, 0x32, 0x8a, 0x77, 0xd0, 0xec, 0x99, + 0x07, 0x60, 0x25, 0x69, 0xee, 0x23, 0xd7, 0xa2, 0xb0, 0x76, 0xae, 0xb2, 0xc1, 0xed, 0xb9, 0x83, + 0xa6, 0xc4, 0x12, 0x2d, 0x8d, 0xa1, 0x45, 0x60, 0xe1, 0xca, 0x04, 0x70, 0xa0, 0xf4, 0x14, 0x5d, + 0xfa, 0x63, 0x2d, 0xc7, 0x91, 0x86, 0x8b, 0xce, 0xa7, 0xfc, 0x10, 0x65, 0xe2, 0x8d, 0x30, 0xc6, + 0xd4, 0x2b, 0xbc, 0xb0, 0x3a, 0x19, 0x8f, 0x25, 0x2b, 0x95, 0x83, 0x23, 0x43, 0x3f, 0x3c, 0x32, + 0xf4, 0x6f, 0x47, 0x86, 0xfe, 0xe6, 0xd8, 0xd0, 0x0e, 0x8f, 0x0d, 0xed, 0xf3, 0xb1, 0xa1, 0x3d, + 0x9b, 0x7c, 0xb4, 0x7b, 0xe2, 0xfd, 0x17, 0x07, 0x5c, 0x9b, 0x16, 0x0f, 0xef, 0xb5, 0xdf, 0x01, + 0x00, 0x00, 0xff, 0xff, 0x77, 0xea, 0x20, 0x5e, 0x6b, 0x06, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -338,6 +381,8 @@ type MsgClient interface { SubmitProposal(ctx context.Context, in *MsgSubmitProposal, opts ...grpc.CallOption) (*MsgSubmitProposalResponse, error) // Vote defines a method to add a vote on a specific proposal. Vote(ctx context.Context, in *MsgVote, opts ...grpc.CallOption) (*MsgVoteResponse, error) + // WeightedVote defines a method to add a weighted vote on a specific proposal. + WeightedVote(ctx context.Context, in *MsgWeightedVote, opts ...grpc.CallOption) (*MsgVoteResponse, error) // Deposit defines a method to add deposit on a specific proposal. Deposit(ctx context.Context, in *MsgDeposit, opts ...grpc.CallOption) (*MsgDepositResponse, error) } @@ -368,6 +413,15 @@ func (c *msgClient) Vote(ctx context.Context, in *MsgVote, opts ...grpc.CallOpti return out, nil } +func (c *msgClient) WeightedVote(ctx context.Context, in *MsgWeightedVote, opts ...grpc.CallOption) (*MsgVoteResponse, error) { + out := new(MsgVoteResponse) + err := c.cc.Invoke(ctx, "/cosmos.gov.v1beta1.Msg/WeightedVote", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *msgClient) Deposit(ctx context.Context, in *MsgDeposit, opts ...grpc.CallOption) (*MsgDepositResponse, error) { out := new(MsgDepositResponse) err := c.cc.Invoke(ctx, "/cosmos.gov.v1beta1.Msg/Deposit", in, out, opts...) @@ -383,6 +437,8 @@ type MsgServer interface { SubmitProposal(context.Context, *MsgSubmitProposal) (*MsgSubmitProposalResponse, error) // Vote defines a method to add a vote on a specific proposal. Vote(context.Context, *MsgVote) (*MsgVoteResponse, error) + // WeightedVote defines a method to add a weighted vote on a specific proposal. + WeightedVote(context.Context, *MsgWeightedVote) (*MsgVoteResponse, error) // Deposit defines a method to add deposit on a specific proposal. Deposit(context.Context, *MsgDeposit) (*MsgDepositResponse, error) } @@ -397,6 +453,9 @@ func (*UnimplementedMsgServer) SubmitProposal(ctx context.Context, req *MsgSubmi func (*UnimplementedMsgServer) Vote(ctx context.Context, req *MsgVote) (*MsgVoteResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Vote not implemented") } +func (*UnimplementedMsgServer) WeightedVote(ctx context.Context, req *MsgWeightedVote) (*MsgVoteResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method WeightedVote not implemented") +} func (*UnimplementedMsgServer) Deposit(ctx context.Context, req *MsgDeposit) (*MsgDepositResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Deposit not implemented") } @@ -441,6 +500,24 @@ func _Msg_Vote_Handler(srv interface{}, ctx context.Context, dec func(interface{ return interceptor(ctx, in, info, handler) } +func _Msg_WeightedVote_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgWeightedVote) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).WeightedVote(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.gov.v1beta1.Msg/WeightedVote", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).WeightedVote(ctx, req.(*MsgWeightedVote)) + } + return interceptor(ctx, in, info, handler) +} + func _Msg_Deposit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(MsgDeposit) if err := dec(in); err != nil { @@ -471,6 +548,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "Vote", Handler: _Msg_Vote_Handler, }, + { + MethodName: "WeightedVote", + Handler: _Msg_WeightedVote_Handler, + }, { MethodName: "Deposit", Handler: _Msg_Deposit_Handler, @@ -580,6 +661,46 @@ func (m *MsgVote) MarshalTo(dAtA []byte) (int, error) { } func (m *MsgVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Option != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Option)) + i-- + dAtA[i] = 0x18 + } + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintTx(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0x12 + } + if m.ProposalId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgWeightedVote) 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 *MsgWeightedVote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgWeightedVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -755,6 +876,25 @@ func (m *MsgSubmitProposalResponse) Size() (n int) { } func (m *MsgVote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovTx(uint64(m.ProposalId)) + } + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Option != 0 { + n += 1 + sovTx(uint64(m.Option)) + } + return n +} + +func (m *MsgWeightedVote) Size() (n int) { if m == nil { return 0 } @@ -1078,6 +1218,129 @@ func (m *MsgVote) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: MsgVote: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Voter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Option", wireType) + } + m.Option = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Option |= VoteOption(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgWeightedVote) 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 ErrIntOverflowTx + } + 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: MsgWeightedVote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgWeightedVote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { case 1: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) From 350f88c0ca69d7f838332825f071ace14c236966 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Tue, 3 Nov 2020 22:21:23 +1000 Subject: [PATCH 013/152] fix lint issues --- proto/cosmos/gov/v1beta1/tx.proto | 7 +- x/gov/client/utils/query.go | 25 ++-- x/gov/keeper/msg_server.go | 4 +- x/gov/types/tx.pb.go | 223 +++++++++++++++++++++++------- 4 files changed, 195 insertions(+), 64 deletions(-) diff --git a/proto/cosmos/gov/v1beta1/tx.proto b/proto/cosmos/gov/v1beta1/tx.proto index 3fb754d14292..0d8cbc03ce4c 100644 --- a/proto/cosmos/gov/v1beta1/tx.proto +++ b/proto/cosmos/gov/v1beta1/tx.proto @@ -18,7 +18,7 @@ service Msg { rpc Vote(MsgVote) returns (MsgVoteResponse); // WeightedVote defines a method to add a weighted vote on a specific proposal. - rpc WeightedVote(MsgWeightedVote) returns (MsgVoteResponse); + rpc WeightedVote(MsgWeightedVote) returns (MsgWeightedVoteResponse); // Deposit defines a method to add deposit on a specific proposal. rpc Deposit(MsgDeposit) returns (MsgDepositResponse); @@ -53,7 +53,7 @@ message MsgVote { option (gogoproto.stringer) = false; option (gogoproto.goproto_getters) = false; - uint64 proposal_id = 1 [(gogoproto.moretags) = "yaml:\"proposal_id\""]; + uint64 proposal_id = 1 [(gogoproto.jsontag) = "proposal_id", (gogoproto.moretags) = "yaml:\"proposal_id\""]; string voter = 2; VoteOption option = 3; } @@ -73,6 +73,9 @@ message MsgWeightedVote { // MsgVoteResponse defines the Msg/Vote response type. message MsgVoteResponse {} +// MsgWeightedVoteResponse defines the MsgWeightedVote response type. +message MsgWeightedVoteResponse {} + // MsgDeposit defines a message to submit a deposit to an existing proposal. message MsgDeposit { option (gogoproto.equal) = false; diff --git a/x/gov/client/utils/query.go b/x/gov/client/utils/query.go index 3f92d6230819..922da03f5640 100644 --- a/x/gov/client/utils/query.go +++ b/x/gov/client/utils/query.go @@ -150,33 +150,38 @@ func QueryVoteByTxQuery(clientCtx client.Context, params types.QueryVoteParams) } for _, info := range searchResult.Txs { for _, msg := range info.GetTx().GetMsgs() { - vote := types.Vote{} - // there should only be a single vote under the given conditions if msg.Type() == types.TypeMsgVote { voteMsg := msg.(*types.MsgVote) - vote = types.Vote{ + vote := types.Vote{ Voter: voteMsg.Voter, ProposalId: params.ProposalID, Options: types.NewNonSplitVoteOption(voteMsg.Option), } + + bz, err := clientCtx.JSONMarshaler.MarshalJSON(&vote) + if err != nil { + return nil, err + } + + return bz, nil } else if msg.Type() == types.TypeMsgWeightedVote { voteMsg := msg.(*types.MsgWeightedVote) - vote = types.Vote{ + vote := types.Vote{ Voter: voteMsg.Voter, ProposalId: params.ProposalID, Options: voteMsg.Options, } - } - bz, err := clientCtx.JSONMarshaler.MarshalJSON(&vote) - if err != nil { - return nil, err - } + bz, err := clientCtx.JSONMarshaler.MarshalJSON(&vote) + if err != nil { + return nil, err + } - return bz, nil + return bz, nil + } } } diff --git a/x/gov/keeper/msg_server.go b/x/gov/keeper/msg_server.go index 3d02ae95e8b4..84cc74e776cf 100644 --- a/x/gov/keeper/msg_server.go +++ b/x/gov/keeper/msg_server.go @@ -88,7 +88,7 @@ func (k msgServer) Vote(goCtx context.Context, msg *types.MsgVote) (*types.MsgVo return &types.MsgVoteResponse{}, nil } -func (k msgServer) WeightedVote(goCtx context.Context, msg *types.MsgWeightedVote) (*types.MsgVoteResponse, error) { +func (k msgServer) WeightedVote(goCtx context.Context, msg *types.MsgWeightedVote) (*types.MsgWeightedVoteResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) accAddr, accErr := sdk.AccAddressFromBech32(msg.Voter) if accErr != nil { @@ -115,7 +115,7 @@ func (k msgServer) WeightedVote(goCtx context.Context, msg *types.MsgWeightedVot ), ) - return &types.MsgVoteResponse{}, nil + return &types.MsgWeightedVoteResponse{}, nil } func (k msgServer) Deposit(goCtx context.Context, msg *types.MsgDeposit) (*types.MsgDepositResponse, error) { diff --git a/x/gov/types/tx.pb.go b/x/gov/types/tx.pb.go index 71222492cf19..29ed22443d27 100644 --- a/x/gov/types/tx.pb.go +++ b/x/gov/types/tx.pb.go @@ -119,7 +119,7 @@ func (m *MsgSubmitProposalResponse) GetProposalId() uint64 { // MsgVote defines a message to cast a vote. type MsgVote struct { - ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty" yaml:"proposal_id"` + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id" yaml:"proposal_id"` Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` Option VoteOption `protobuf:"varint,3,opt,name=option,proto3,enum=cosmos.gov.v1beta1.VoteOption" json:"option,omitempty"` } @@ -232,6 +232,43 @@ func (m *MsgVoteResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgVoteResponse proto.InternalMessageInfo +// MsgWeightedVoteResponse defines the MsgWeightedVote response type. +type MsgWeightedVoteResponse struct { +} + +func (m *MsgWeightedVoteResponse) Reset() { *m = MsgWeightedVoteResponse{} } +func (m *MsgWeightedVoteResponse) String() string { return proto.CompactTextString(m) } +func (*MsgWeightedVoteResponse) ProtoMessage() {} +func (*MsgWeightedVoteResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_3c053992595e3dce, []int{5} +} +func (m *MsgWeightedVoteResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgWeightedVoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgWeightedVoteResponse.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 *MsgWeightedVoteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgWeightedVoteResponse.Merge(m, src) +} +func (m *MsgWeightedVoteResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgWeightedVoteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgWeightedVoteResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgWeightedVoteResponse proto.InternalMessageInfo + // MsgDeposit defines a message to submit a deposit to an existing proposal. type MsgDeposit struct { ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id" yaml:"proposal_id"` @@ -242,7 +279,7 @@ type MsgDeposit struct { func (m *MsgDeposit) Reset() { *m = MsgDeposit{} } func (*MsgDeposit) ProtoMessage() {} func (*MsgDeposit) Descriptor() ([]byte, []int) { - return fileDescriptor_3c053992595e3dce, []int{5} + return fileDescriptor_3c053992595e3dce, []int{6} } func (m *MsgDeposit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -279,7 +316,7 @@ func (m *MsgDepositResponse) Reset() { *m = MsgDepositResponse{} } func (m *MsgDepositResponse) String() string { return proto.CompactTextString(m) } func (*MsgDepositResponse) ProtoMessage() {} func (*MsgDepositResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_3c053992595e3dce, []int{6} + return fileDescriptor_3c053992595e3dce, []int{7} } func (m *MsgDepositResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -314,6 +351,7 @@ func init() { proto.RegisterType((*MsgVote)(nil), "cosmos.gov.v1beta1.MsgVote") proto.RegisterType((*MsgWeightedVote)(nil), "cosmos.gov.v1beta1.MsgWeightedVote") proto.RegisterType((*MsgVoteResponse)(nil), "cosmos.gov.v1beta1.MsgVoteResponse") + proto.RegisterType((*MsgWeightedVoteResponse)(nil), "cosmos.gov.v1beta1.MsgWeightedVoteResponse") proto.RegisterType((*MsgDeposit)(nil), "cosmos.gov.v1beta1.MsgDeposit") proto.RegisterType((*MsgDepositResponse)(nil), "cosmos.gov.v1beta1.MsgDepositResponse") } @@ -321,48 +359,48 @@ func init() { func init() { proto.RegisterFile("cosmos/gov/v1beta1/tx.proto", fileDescriptor_3c053992595e3dce) } var fileDescriptor_3c053992595e3dce = []byte{ - // 652 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xb1, 0x6f, 0xd3, 0x4e, - 0x14, 0xb6, 0x93, 0xfe, 0x9a, 0x5f, 0x2f, 0xa8, 0xa5, 0xa7, 0xa8, 0x4a, 0xd3, 0xca, 0x8e, 0x8c, - 0x5a, 0x65, 0xa9, 0x4d, 0x83, 0x04, 0x52, 0x99, 0x48, 0x51, 0x05, 0x48, 0x11, 0x60, 0x24, 0x40, - 0x2c, 0x95, 0x93, 0x5c, 0xaf, 0x16, 0x89, 0x9f, 0x95, 0xbb, 0x44, 0xcd, 0xc6, 0xc8, 0x04, 0x8c, - 0x8c, 0x15, 0x23, 0x33, 0x7f, 0x44, 0x61, 0xea, 0xc8, 0x80, 0x02, 0x6a, 0x19, 0x80, 0xb1, 0x7f, - 0x01, 0xf2, 0xdd, 0x39, 0x0d, 0x8d, 0x13, 0x8a, 0xd4, 0x29, 0x79, 0xef, 0x7b, 0xdf, 0xe7, 0xf7, - 0xbd, 0x7b, 0x77, 0x68, 0xa9, 0x0e, 0xac, 0x05, 0xcc, 0xa1, 0xd0, 0x75, 0xba, 0xeb, 0x35, 0xc2, - 0xbd, 0x75, 0x87, 0xef, 0xd9, 0x61, 0x1b, 0x38, 0x60, 0x2c, 0x41, 0x9b, 0x42, 0xd7, 0x56, 0x60, - 0xc1, 0x50, 0x84, 0x9a, 0xc7, 0xc8, 0x80, 0x51, 0x07, 0x3f, 0x90, 0x9c, 0xc2, 0x72, 0x82, 0x60, - 0xc4, 0x97, 0xe8, 0xa2, 0x44, 0xb7, 0x45, 0xe4, 0x28, 0x79, 0x09, 0xe5, 0x28, 0x50, 0x90, 0xf9, - 0xe8, 0x5f, 0x4c, 0xa0, 0x00, 0xb4, 0x49, 0x1c, 0x11, 0xd5, 0x3a, 0x3b, 0x8e, 0x17, 0xf4, 0x24, - 0x64, 0xbd, 0x4e, 0xa1, 0xf9, 0x2a, 0xa3, 0x8f, 0x3a, 0xb5, 0x96, 0xcf, 0x1f, 0xb4, 0x21, 0x04, - 0xe6, 0x35, 0xf1, 0x4d, 0x94, 0xa9, 0x43, 0xc0, 0x49, 0xc0, 0xf3, 0x7a, 0x51, 0x2f, 0x65, 0xcb, - 0x39, 0x5b, 0x4a, 0xd8, 0xb1, 0x84, 0x7d, 0x2b, 0xe8, 0x55, 0xb2, 0x9f, 0x3e, 0xac, 0x65, 0x36, - 0x65, 0xa1, 0x1b, 0x33, 0xf0, 0x2b, 0x1d, 0xcd, 0xf9, 0x81, 0xcf, 0x7d, 0xaf, 0xb9, 0xdd, 0x20, - 0x21, 0x30, 0x9f, 0xe7, 0x53, 0xc5, 0x74, 0x29, 0x5b, 0x5e, 0xb4, 0x55, 0xb3, 0x91, 0xef, 0x78, - 0x18, 0xf6, 0x26, 0xf8, 0x41, 0xe5, 0xde, 0x41, 0xdf, 0xd4, 0x4e, 0xfa, 0xe6, 0x42, 0xcf, 0x6b, - 0x35, 0x37, 0xac, 0x33, 0x7c, 0xeb, 0xfd, 0x57, 0xb3, 0x44, 0x7d, 0xbe, 0xdb, 0xa9, 0xd9, 0x75, - 0x68, 0x29, 0xcf, 0xea, 0x67, 0x8d, 0x35, 0x9e, 0x3b, 0xbc, 0x17, 0x12, 0x26, 0xa4, 0x98, 0x3b, - 0xab, 0xd8, 0xb7, 0x25, 0x19, 0x17, 0xd0, 0xff, 0xa1, 0x70, 0x46, 0xda, 0xf9, 0x74, 0x51, 0x2f, - 0xcd, 0xb8, 0x83, 0x78, 0xe3, 0xf2, 0xcb, 0x7d, 0x53, 0x7b, 0xbb, 0x6f, 0x6a, 0x3f, 0xf6, 0x4d, - 0xed, 0xc5, 0x97, 0xa2, 0x66, 0xd5, 0xd1, 0xe2, 0xc8, 0x40, 0x5c, 0xc2, 0x42, 0x08, 0x18, 0xc1, - 0x5b, 0x28, 0x1b, 0xaa, 0xdc, 0xb6, 0xdf, 0x10, 0xc3, 0x99, 0xaa, 0xac, 0xfc, 0xea, 0x9b, 0xc3, - 0xe9, 0x93, 0xbe, 0x89, 0xa5, 0x8d, 0xa1, 0xa4, 0xe5, 0xa2, 0x38, 0xba, 0xdb, 0xb0, 0xde, 0xe9, - 0x28, 0x53, 0x65, 0xf4, 0x31, 0x70, 0x82, 0x6f, 0x24, 0x69, 0x2e, 0xfc, 0x5d, 0x04, 0xe7, 0xd0, - 0x7f, 0x5d, 0xe0, 0xa4, 0x9d, 0x4f, 0x09, 0x53, 0x32, 0xc0, 0xd7, 0xd1, 0x34, 0x84, 0xdc, 0x87, - 0x40, 0x78, 0x9d, 0x2d, 0x1b, 0xf6, 0xe8, 0x02, 0xda, 0xd1, 0x87, 0xef, 0x8b, 0x2a, 0x57, 0x55, - 0x27, 0x4c, 0xe2, 0xa3, 0x8e, 0xe6, 0xaa, 0x8c, 0x3e, 0x21, 0x3e, 0xdd, 0xe5, 0xa4, 0x21, 0x9a, - 0xbd, 0xa0, 0x01, 0x8c, 0xe9, 0x7d, 0x0b, 0x65, 0x64, 0x37, 0x2c, 0x9f, 0x16, 0x1b, 0xb3, 0x9a, - 0xd4, 0xfc, 0x70, 0x43, 0xd2, 0x44, 0x65, 0x2a, 0x5a, 0x1f, 0x37, 0x26, 0x27, 0x78, 0x99, 0x17, - 0x56, 0x22, 0x46, 0x7c, 0x96, 0xd6, 0x4f, 0x1d, 0xa1, 0x2a, 0xa3, 0xf1, 0x96, 0x5c, 0x94, 0xb3, - 0x65, 0x34, 0xa3, 0xb6, 0x16, 0x62, 0x77, 0xa7, 0x09, 0x5c, 0x47, 0xd3, 0x5e, 0x0b, 0x3a, 0x01, - 0x57, 0x06, 0x27, 0x5c, 0x89, 0xab, 0x91, 0xa7, 0x7f, 0x5a, 0x7c, 0x25, 0x9d, 0x60, 0x3f, 0x87, - 0xf0, 0xa9, 0xd5, 0x78, 0x02, 0xe5, 0xef, 0x29, 0x94, 0xae, 0x32, 0x8a, 0x77, 0xd0, 0xec, 0x99, - 0x07, 0x60, 0x25, 0x69, 0xee, 0x23, 0xd7, 0xa2, 0xb0, 0x76, 0xae, 0xb2, 0xc1, 0xed, 0xb9, 0x83, - 0xa6, 0xc4, 0x12, 0x2d, 0x8d, 0xa1, 0x45, 0x60, 0xe1, 0xca, 0x04, 0x70, 0xa0, 0xf4, 0x14, 0x5d, - 0xfa, 0x63, 0x2d, 0xc7, 0x91, 0x86, 0x8b, 0xce, 0xa7, 0xfc, 0x10, 0x65, 0xe2, 0x8d, 0x30, 0xc6, - 0xd4, 0x2b, 0xbc, 0xb0, 0x3a, 0x19, 0x8f, 0x25, 0x2b, 0x95, 0x83, 0x23, 0x43, 0x3f, 0x3c, 0x32, - 0xf4, 0x6f, 0x47, 0x86, 0xfe, 0xe6, 0xd8, 0xd0, 0x0e, 0x8f, 0x0d, 0xed, 0xf3, 0xb1, 0xa1, 0x3d, - 0x9b, 0x7c, 0xb4, 0x7b, 0xe2, 0xfd, 0x17, 0x07, 0x5c, 0x9b, 0x16, 0x0f, 0xef, 0xb5, 0xdf, 0x01, - 0x00, 0x00, 0xff, 0xff, 0x77, 0xea, 0x20, 0x5e, 0x6b, 0x06, 0x00, 0x00, + // 655 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0xc1, 0x6b, 0x13, 0x4f, + 0x14, 0xde, 0x4d, 0xfa, 0x6b, 0x7e, 0x7d, 0x91, 0xd6, 0x2e, 0x41, 0x93, 0x6d, 0xd9, 0x0d, 0x2b, + 0x2d, 0x01, 0xe9, 0xae, 0x8d, 0xe0, 0xa1, 0x9e, 0x4c, 0xa5, 0xa8, 0x10, 0xd4, 0x15, 0x14, 0xbc, + 0xd4, 0x4d, 0xb2, 0x9d, 0x2e, 0x26, 0xfb, 0x96, 0xcc, 0x24, 0x34, 0x37, 0x8f, 0x9e, 0xd4, 0xa3, + 0xc7, 0x9e, 0xbd, 0x09, 0xfe, 0x11, 0xd5, 0x53, 0x8f, 0x1e, 0x24, 0x4a, 0x7b, 0x51, 0xf1, 0xd4, + 0xbf, 0x40, 0x76, 0x66, 0x36, 0x8d, 0x6d, 0x12, 0x2a, 0x14, 0x4f, 0xc9, 0x7b, 0xdf, 0xfb, 0xbe, + 0xbc, 0xef, 0xcd, 0x9b, 0x09, 0x2c, 0xd4, 0x91, 0xb6, 0x90, 0x3a, 0x04, 0xbb, 0x4e, 0x77, 0xb5, + 0xe6, 0x33, 0x6f, 0xd5, 0x61, 0x3b, 0x76, 0xd4, 0x46, 0x86, 0x9a, 0x26, 0x40, 0x9b, 0x60, 0xd7, + 0x96, 0xa0, 0x6e, 0x48, 0x42, 0xcd, 0xa3, 0xfe, 0x80, 0x51, 0xc7, 0x20, 0x14, 0x1c, 0x7d, 0x71, + 0x84, 0x60, 0xcc, 0x17, 0x68, 0x41, 0xa0, 0x9b, 0x3c, 0x72, 0xa4, 0xbc, 0x80, 0x72, 0x04, 0x09, + 0x8a, 0x7c, 0xfc, 0x2d, 0x21, 0x10, 0x44, 0xd2, 0xf4, 0x1d, 0x1e, 0xd5, 0x3a, 0x5b, 0x8e, 0x17, + 0xf6, 0x04, 0x64, 0xbd, 0x4e, 0xc1, 0x7c, 0x95, 0x92, 0x47, 0x9d, 0x5a, 0x2b, 0x60, 0x0f, 0xda, + 0x18, 0x21, 0xf5, 0x9a, 0xda, 0x4d, 0xc8, 0xd4, 0x31, 0x64, 0x7e, 0xc8, 0xf2, 0x6a, 0x51, 0x2d, + 0x65, 0xcb, 0x39, 0x5b, 0x48, 0xd8, 0x89, 0x84, 0x7d, 0x2b, 0xec, 0x55, 0xb2, 0x9f, 0x3e, 0xac, + 0x64, 0xd6, 0x45, 0xa1, 0x9b, 0x30, 0xb4, 0x57, 0x2a, 0xcc, 0x05, 0x61, 0xc0, 0x02, 0xaf, 0xb9, + 0xd9, 0xf0, 0x23, 0xa4, 0x01, 0xcb, 0xa7, 0x8a, 0xe9, 0x52, 0xb6, 0x5c, 0xb0, 0x65, 0xb3, 0xb1, + 0xef, 0x64, 0x18, 0xf6, 0x3a, 0x06, 0x61, 0xe5, 0xde, 0x5e, 0xdf, 0x54, 0x8e, 0xfa, 0xe6, 0xa5, + 0x9e, 0xd7, 0x6a, 0xae, 0x59, 0x27, 0xf8, 0xd6, 0xbb, 0xaf, 0x66, 0x89, 0x04, 0x6c, 0xbb, 0x53, + 0xb3, 0xeb, 0xd8, 0x92, 0x9e, 0xe5, 0xc7, 0x0a, 0x6d, 0x3c, 0x77, 0x58, 0x2f, 0xf2, 0x29, 0x97, + 0xa2, 0xee, 0xac, 0x64, 0xdf, 0x16, 0x64, 0x4d, 0x87, 0xff, 0x23, 0xee, 0xcc, 0x6f, 0xe7, 0xd3, + 0x45, 0xb5, 0x34, 0xe3, 0x0e, 0xe2, 0xb5, 0x8b, 0x2f, 0x77, 0x4d, 0xe5, 0xed, 0xae, 0xa9, 0x7c, + 0xdf, 0x35, 0x95, 0x17, 0x5f, 0x8a, 0x8a, 0x55, 0x87, 0xc2, 0xa9, 0x81, 0xb8, 0x3e, 0x8d, 0x30, + 0xa4, 0xbe, 0xb6, 0x01, 0xd9, 0x48, 0xe6, 0x36, 0x83, 0x06, 0x1f, 0xce, 0x54, 0x65, 0xe9, 0x67, + 0xdf, 0x1c, 0x4e, 0x1f, 0xf5, 0x4d, 0x4d, 0xd8, 0x18, 0x4a, 0x5a, 0x2e, 0x24, 0xd1, 0xdd, 0x86, + 0xf5, 0x5e, 0x85, 0x4c, 0x95, 0x92, 0xc7, 0xc8, 0xce, 0x4d, 0x53, 0xcb, 0xc1, 0x7f, 0x5d, 0x64, + 0x7e, 0x3b, 0x9f, 0xe2, 0x1e, 0x45, 0xa0, 0xdd, 0x80, 0x69, 0x8c, 0x58, 0x80, 0x21, 0xb7, 0x3e, + 0x5b, 0x36, 0xec, 0xd3, 0xfb, 0x68, 0xc7, 0x7d, 0xdc, 0xe7, 0x55, 0xae, 0xac, 0x1e, 0x31, 0x98, + 0x8f, 0x2a, 0xcc, 0x55, 0x29, 0x79, 0xe2, 0x07, 0x64, 0x9b, 0xf9, 0x8d, 0x7f, 0xd0, 0xfb, 0x06, + 0x64, 0x44, 0x37, 0x34, 0x9f, 0xe6, 0x0b, 0xb4, 0x3c, 0xaa, 0xf9, 0xe1, 0x86, 0x84, 0x89, 0xca, + 0x54, 0xbc, 0x4d, 0x6e, 0x42, 0x1e, 0xe1, 0x65, 0x9e, 0x5b, 0x89, 0x19, 0xc9, 0xd1, 0x5a, 0x05, + 0xb8, 0x7c, 0xc2, 0xdd, 0x00, 0xfa, 0xa1, 0x02, 0x54, 0x29, 0x49, 0xf6, 0xe9, 0xbc, 0x4c, 0x2f, + 0xc2, 0x8c, 0xdc, 0x6f, 0x4c, 0x8c, 0x1f, 0x27, 0xb4, 0x3a, 0x4c, 0x7b, 0x2d, 0xec, 0x84, 0x4c, + 0x7a, 0x9f, 0x70, 0x79, 0xae, 0xc5, 0x76, 0xff, 0xea, 0x8a, 0x48, 0xe9, 0x11, 0x93, 0xc9, 0x81, + 0x76, 0x6c, 0x35, 0x99, 0x40, 0xf9, 0x57, 0x0a, 0xd2, 0x55, 0x4a, 0xb4, 0x2d, 0x98, 0x3d, 0xf1, + 0x54, 0x2c, 0x8d, 0x3a, 0x92, 0x53, 0x17, 0x48, 0x5f, 0x39, 0x53, 0xd9, 0xe0, 0x9e, 0xdd, 0x81, + 0x29, 0xbe, 0x5f, 0x0b, 0x63, 0x68, 0x31, 0xa8, 0x5f, 0x99, 0x00, 0x0e, 0x94, 0x9e, 0xc1, 0x85, + 0x3f, 0x36, 0x76, 0x1c, 0x69, 0xb8, 0x48, 0xbf, 0x7a, 0x86, 0xa2, 0xc1, 0x2f, 0x3c, 0x84, 0x4c, + 0xb2, 0x19, 0xc6, 0x18, 0x9e, 0xc4, 0xf5, 0xe5, 0xc9, 0x78, 0x22, 0x59, 0xa9, 0xec, 0x1d, 0x18, + 0xea, 0xfe, 0x81, 0xa1, 0x7e, 0x3b, 0x30, 0xd4, 0x37, 0x87, 0x86, 0xb2, 0x7f, 0x68, 0x28, 0x9f, + 0x0f, 0x0d, 0xe5, 0xe9, 0xe4, 0x23, 0xde, 0xe1, 0xff, 0x18, 0xfc, 0xa0, 0x6b, 0xd3, 0xfc, 0xa9, + 0xbe, 0xfe, 0x3b, 0x00, 0x00, 0xff, 0xff, 0xc9, 0x6e, 0x76, 0x95, 0x9d, 0x06, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -382,7 +420,7 @@ type MsgClient interface { // Vote defines a method to add a vote on a specific proposal. Vote(ctx context.Context, in *MsgVote, opts ...grpc.CallOption) (*MsgVoteResponse, error) // WeightedVote defines a method to add a weighted vote on a specific proposal. - WeightedVote(ctx context.Context, in *MsgWeightedVote, opts ...grpc.CallOption) (*MsgVoteResponse, error) + WeightedVote(ctx context.Context, in *MsgWeightedVote, opts ...grpc.CallOption) (*MsgWeightedVoteResponse, error) // Deposit defines a method to add deposit on a specific proposal. Deposit(ctx context.Context, in *MsgDeposit, opts ...grpc.CallOption) (*MsgDepositResponse, error) } @@ -413,8 +451,8 @@ func (c *msgClient) Vote(ctx context.Context, in *MsgVote, opts ...grpc.CallOpti return out, nil } -func (c *msgClient) WeightedVote(ctx context.Context, in *MsgWeightedVote, opts ...grpc.CallOption) (*MsgVoteResponse, error) { - out := new(MsgVoteResponse) +func (c *msgClient) WeightedVote(ctx context.Context, in *MsgWeightedVote, opts ...grpc.CallOption) (*MsgWeightedVoteResponse, error) { + out := new(MsgWeightedVoteResponse) err := c.cc.Invoke(ctx, "/cosmos.gov.v1beta1.Msg/WeightedVote", in, out, opts...) if err != nil { return nil, err @@ -438,7 +476,7 @@ type MsgServer interface { // Vote defines a method to add a vote on a specific proposal. Vote(context.Context, *MsgVote) (*MsgVoteResponse, error) // WeightedVote defines a method to add a weighted vote on a specific proposal. - WeightedVote(context.Context, *MsgWeightedVote) (*MsgVoteResponse, error) + WeightedVote(context.Context, *MsgWeightedVote) (*MsgWeightedVoteResponse, error) // Deposit defines a method to add deposit on a specific proposal. Deposit(context.Context, *MsgDeposit) (*MsgDepositResponse, error) } @@ -453,7 +491,7 @@ func (*UnimplementedMsgServer) SubmitProposal(ctx context.Context, req *MsgSubmi func (*UnimplementedMsgServer) Vote(ctx context.Context, req *MsgVote) (*MsgVoteResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Vote not implemented") } -func (*UnimplementedMsgServer) WeightedVote(ctx context.Context, req *MsgWeightedVote) (*MsgVoteResponse, error) { +func (*UnimplementedMsgServer) WeightedVote(ctx context.Context, req *MsgWeightedVote) (*MsgWeightedVoteResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method WeightedVote not implemented") } func (*UnimplementedMsgServer) Deposit(ctx context.Context, req *MsgDeposit) (*MsgDepositResponse, error) { @@ -757,6 +795,29 @@ func (m *MsgVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *MsgWeightedVoteResponse) 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 *MsgWeightedVoteResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgWeightedVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func (m *MsgDeposit) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -925,6 +986,15 @@ func (m *MsgVoteResponse) Size() (n int) { return n } +func (m *MsgWeightedVoteResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func (m *MsgDeposit) Size() (n int) { if m == nil { return 0 @@ -1503,6 +1573,59 @@ func (m *MsgVoteResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgWeightedVoteResponse) 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 ErrIntOverflowTx + } + 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: MsgWeightedVoteResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgWeightedVoteResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *MsgDeposit) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 From 381d1b0e7096ca2dc8ea0183a6ad3141ae606673 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Tue, 3 Nov 2020 22:32:49 +1000 Subject: [PATCH 014/152] fix deprecated function use after merging cosmos master --- x/gov/simulation/operations.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/gov/simulation/operations.go b/x/gov/simulation/operations.go index 83122daebba5..9e3dcae964a6 100644 --- a/x/gov/simulation/operations.go +++ b/x/gov/simulation/operations.go @@ -366,7 +366,7 @@ func operationSimulateMsgWeightedVote(ak types.AccountKeeper, bk types.BankKeepe return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to generate fees"), nil, err } - txGen := simappparams.MakeEncodingConfig().TxConfig + txGen := simappparams.MakeTestEncodingConfig().TxConfig tx, err := helpers.GenTx( txGen, []sdk.Msg{msg}, From 7fc5e3e6ab71fc6643176773e301d87b729ce549 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Thu, 7 Jan 2021 22:50:52 +0100 Subject: [PATCH 015/152] codecs: rename MakeCodecs rename and docs update (#8245) * codecs: rename MakeCodecs to MakeTestCodecs * update changelog * remove MakeTestCodecs * typo --- CHANGELOG.md | 2 ++ codec/amino_codec_test.go | 3 +-- docs/basics/app-anatomy.md | 12 +++++++----- simapp/app.go | 9 --------- simapp/encoding.go | 6 +++--- simapp/simd/cmd/genaccounts_test.go | 2 +- x/auth/ante/sigverify_test.go | 2 +- x/auth/keeper/keeper_test.go | 2 +- x/auth/simulation/decoder_test.go | 2 +- x/auth/types/common_test.go | 3 ++- x/auth/vesting/types/common_test.go | 4 ++-- x/bank/keeper/keeper_test.go | 2 +- x/capability/simulation/decoder_test.go | 2 +- x/distribution/simulation/decoder_test.go | 2 +- x/evidence/keeper/querier_test.go | 12 ++++++------ x/gov/keeper/common_test.go | 4 ++-- x/gov/simulation/decoder_test.go | 3 +-- x/mint/simulation/decoder_test.go | 2 +- x/slashing/simulation/decoder_test.go | 2 +- x/staking/keeper/grpc_query_test.go | 5 ++--- x/staking/simulation/decoder_test.go | 3 +-- 21 files changed, 38 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 776c3c0ac755..524a4661a523 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -122,6 +122,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ + added `overwriteSig` argument to `x/auth/client.SignTx` and `client/tx.Sign` functions. + removed `x/auth/tx.go:wrapper.GetSignatures`. The `wrapper` provides `TxBuilder` functionality, and it's a private structure. That function was not used at all and it's not exposed through the `TxBuilder` interface. +* [\#8245](https://github.com/cosmos/cosmos-sdk/pull/8245) Removed `simapp.MakeCodecs` and use `simapp.MakeTestEncodingConfig` instead. + ### Bug Fixes diff --git a/codec/amino_codec_test.go b/codec/amino_codec_test.go index d95ddc8d97fa..0526661404d5 100644 --- a/codec/amino_codec_test.go +++ b/codec/amino_codec_test.go @@ -121,8 +121,7 @@ func TestAminoCodecUnpackAnyFails(t *testing.T) { func TestAminoCodecFullDecodeAndEncode(t *testing.T) { // This tx comes from https://github.com/cosmos/cosmos-sdk/issues/8117. txSigned := `{"type":"cosmos-sdk/StdTx","value":{"msg":[{"type":"cosmos-sdk/MsgCreateValidator","value":{"description":{"moniker":"fulltest","identity":"satoshi","website":"example.com","details":"example inc"},"commission":{"rate":"0.500000000000000000","max_rate":"1.000000000000000000","max_change_rate":"0.200000000000000000"},"min_self_delegation":"1000000","delegator_address":"cosmos14pt0q5cwf38zt08uu0n6yrstf3rndzr5057jys","validator_address":"cosmosvaloper14pt0q5cwf38zt08uu0n6yrstf3rndzr52q28gr","pubkey":{"type":"tendermint/PubKeyEd25519","value":"CYrOiM3HtS7uv1B1OAkknZnFYSRpQYSYII8AtMMtev0="},"value":{"denom":"umuon","amount":"700000000"}}}],"fee":{"amount":[{"denom":"umuon","amount":"6000"}],"gas":"160000"},"signatures":[{"pub_key":{"type":"tendermint/PubKeySecp256k1","value":"AwAOXeWgNf1FjMaayrSnrOOKz+Fivr6DiI/i0x0sZCHw"},"signature":"RcnfS/u2yl7uIShTrSUlDWvsXo2p2dYu6WJC8VDVHMBLEQZWc8bsINSCjOnlsIVkUNNe1q/WCA9n3Gy1+0zhYA=="}],"memo":"","timeout_height":"0"}}` - _, legacyCdc := simapp.MakeCodecs() - + var legacyCdc = simapp.MakeTestEncodingConfig().Amino var tx legacytx.StdTx err := legacyCdc.UnmarshalJSON([]byte(txSigned), &tx) require.NoError(t, err) diff --git a/docs/basics/app-anatomy.md b/docs/basics/app-anatomy.md index 9bd2256f0f6a..148ba9ba5da4 100644 --- a/docs/basics/app-anatomy.md +++ b/docs/basics/app-anatomy.md @@ -113,17 +113,19 @@ The `EncodingConfig` structure is the last important part of the `app.go` file. Here are descriptions of what each of the four fields means: -- `InterfaceRegistry`: The `InterfaceRegistry` is used by the Protobuf codec to handle interfaces, which are encoded and decoded (we also say "unpacked") using [`google.protobuf.Any`](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto). `Any` could be thought as a struct which contains a `type_url` (the concrete type of the interface) and a `value` (its encoded bytes). `InterfaceRegistry` provides a mechanism for registering interfaces and implementations that can be safely unpacked from `Any`. Each of the application's modules implements the `RegisterInterfaces` method, which can be used to register the module's own interfaces and implementations. +- `InterfaceRegistry`: The `InterfaceRegistry` is used by the Protobuf codec to handle interfaces, which are encoded and decoded (we also say "unpacked") using [`google.protobuf.Any`](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto). `Any` could be thought as a struct which contains a `type_url` (name of a concrete type implementing the interface) and a `value` (its encoded bytes). `InterfaceRegistry` provides a mechanism for registering interfaces and implementations that can be safely unpacked from `Any`. Each of the application's modules implements the `RegisterInterfaces` method, which can be used to register the module's own interfaces and implementations. + - You can read more about Any in [ADR-19](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-019-protobuf-state-encoding.md#usage-of-any-to-encode-interfaces). - To go more into details, the SDK uses an implementation of the Protobuf specification called [`gogoprotobuf`](https://github.com/gogo/protobuf). By default, the [gogo protobuf implementation of `Any`](https://godoc.org/github.com/gogo/protobuf/types) uses [global type registration](https://github.com/gogo/protobuf/blob/master/proto/properties.go#L540) to decode values packed in `Any` into concrete Go types. This introduces a vulnerability where any malicious module in the dependency tree could registry a type with the global protobuf registry and cause it to be loaded and unmarshaled by a transaction that referenced it in the `type_url` field. For more information, please refer to [ADR-019](../architecture/adr-019-protobuf-state-encoding.md). -- `Marshaler`: The `Marshaler` is the default codec used throughout the SDK. It is composed of a `BinaryMarshaler` used to encode and decode state, and a `JSONMarshaler` used to output data to the users (for example in the [CLI](#cli)). By default, the SDK uses Protobuf as `Marshaler`. +- `Marshaler`: the default codec used throughout the SDK. It is composed of a `BinaryMarshaler` used to encode and decode state, and a `JSONMarshaler` used to output data to the users (for example in the [CLI](#cli)). By default, the SDK uses Protobuf as `Marshaler`. - `TxConfig`: `TxConfig` defines an interface a client can utilize to generate an application-defined concrete transaction type. Currently, the SDK handles two transaction types: `SIGN_MODE_DIRECT` (which uses Protobuf binary as over-the-wire encoding) and `SIGN_MODE_LEGACY_AMINO_JSON` (which depends on Amino). Read more about transactions [here](../core/transactions.md). - `Amino`: Some legacy parts of the SDK still use Amino for backwards-compatibility. Each module exposes a `RegisterLegacyAmino` method to register the module's specific types within Amino. This `Amino` codec should not be used by app developers anymore, and will be removed in future releases. -The SDK exposes a `MakeCodecs` function used to create a `EncodingConfig`. It uses Protobuf as default `Marshaler`, and passes it down to the app's `appCodec` field. It also instantiates a legacy `Amino` codec inside the app's `legacyAmino` field. +The SDK exposes a `MakeTestEncodingConfig` function used to create a `EncodingConfig` for the app constructor (`NewApp`). It uses Protobuf as a default `Marshaler`. +NOTE: this function is marked deprecated and should only be used to create an app or in tests. We are working on refactoring codec management in a post Stargate release. -See an example of a `MakeCodecs` from `simapp`: +See an example of a `MakeTestEncodingConfig` from `simapp`: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/simapp/app.go#L429-L435 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/simapp/simd/cmd/root.go#L179-196 ## Modules diff --git a/simapp/app.go b/simapp/app.go index 02aaa2297fe8..b73538df032d 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -203,7 +203,6 @@ func NewSimApp( appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp), ) *SimApp { - // TODO: Remove cdc in favor of appCodec once all modules are migrated. appCodec := encodingConfig.Marshaler legacyAmino := encodingConfig.Amino interfaceRegistry := encodingConfig.InterfaceRegistry @@ -441,14 +440,6 @@ func NewSimApp( return app } -// MakeCodecs constructs the *std.Codec and *codec.LegacyAmino instances used by -// simapp. It is useful for tests and clients who do not want to construct the -// full simapp -func MakeCodecs() (codec.Marshaler, *codec.LegacyAmino) { - config := MakeTestEncodingConfig() - return config.Marshaler, config.Amino -} - // Name returns the name of the App func (app *SimApp) Name() string { return app.BaseApp.Name() } diff --git a/simapp/encoding.go b/simapp/encoding.go index 954f4a1175eb..8a90ff852478 100644 --- a/simapp/encoding.go +++ b/simapp/encoding.go @@ -5,9 +5,9 @@ import ( "github.com/cosmos/cosmos-sdk/std" ) -// MakeTestEncodingConfig creates an EncodingConfig for testing. -// This function should be used only internally (in the SDK). -// App user should'nt create new codecs - use the app.AppCodec instead. +// MakeTestEncodingConfig creates an EncodingConfig for testing. This function +// should be used only in tests or when creating a new app instance (NewApp*()). +// App user shouldn't create new codecs - use the app.AppCodec instead. // [DEPRECATED] func MakeTestEncodingConfig() simappparams.EncodingConfig { encodingConfig := simappparams.MakeTestEncodingConfig() diff --git a/simapp/simd/cmd/genaccounts_test.go b/simapp/simd/cmd/genaccounts_test.go index 9efc5343e7a3..34fda7b54aac 100644 --- a/simapp/simd/cmd/genaccounts_test.go +++ b/simapp/simd/cmd/genaccounts_test.go @@ -58,7 +58,7 @@ func TestAddGenesisAccountCmd(t *testing.T) { cfg, err := genutiltest.CreateDefaultTendermintConfig(home) require.NoError(t, err) - appCodec, _ := simapp.MakeCodecs() + appCodec := simapp.MakeTestEncodingConfig().Marshaler err = genutiltest.ExecInitCmd(testMbm, home, appCodec) require.NoError(t, err) diff --git a/x/auth/ante/sigverify_test.go b/x/auth/ante/sigverify_test.go index 337618fab50f..fa15e1f179f3 100644 --- a/x/auth/ante/sigverify_test.go +++ b/x/auth/ante/sigverify_test.go @@ -67,7 +67,7 @@ func (suite *AnteTestSuite) TestSetPubKey() { func (suite *AnteTestSuite) TestConsumeSignatureVerificationGas() { params := types.DefaultParams() msg := []byte{1, 2, 3, 4} - _, cdc := simapp.MakeCodecs() + cdc := simapp.MakeTestEncodingConfig().Amino pkSet1, sigSet1 := generatePubKeysAndSignatures(5, msg, false) multisigKey1 := kmultisig.NewLegacyAminoPubKey(2, pkSet1) diff --git a/x/auth/keeper/keeper_test.go b/x/auth/keeper/keeper_test.go index 87744d58c5bb..16cf53a253cf 100644 --- a/x/auth/keeper/keeper_test.go +++ b/x/auth/keeper/keeper_test.go @@ -129,7 +129,7 @@ func TestSupply_ValidatePermissions(t *testing.T) { maccPerms[multiPerm] = []string{types.Burner, types.Minter, types.Staking} maccPerms[randomPerm] = []string{"random"} - cdc, _ := simapp.MakeCodecs() + cdc := simapp.MakeTestEncodingConfig().Marshaler keeper := keeper.NewAccountKeeper( cdc, app.GetKey(types.StoreKey), app.GetSubspace(types.ModuleName), types.ProtoBaseAccount, maccPerms, diff --git a/x/auth/simulation/decoder_test.go b/x/auth/simulation/decoder_test.go index c7ececcf95cc..0caeccee0784 100644 --- a/x/auth/simulation/decoder_test.go +++ b/x/auth/simulation/decoder_test.go @@ -22,7 +22,7 @@ var ( func TestDecodeStore(t *testing.T) { app := simapp.Setup(false) - cdc, _ := simapp.MakeCodecs() + cdc := simapp.MakeTestEncodingConfig().Marshaler acc := types.NewBaseAccountWithAddress(delAddr1) dec := simulation.NewDecodeStore(app.AccountKeeper) diff --git a/x/auth/types/common_test.go b/x/auth/types/common_test.go index 5c6ff0fb6488..8588778994ec 100644 --- a/x/auth/types/common_test.go +++ b/x/auth/types/common_test.go @@ -6,5 +6,6 @@ import ( var ( app = simapp.Setup(false) - appCodec, legacyAmino = simapp.MakeCodecs() + ecdc = simapp.MakeTestEncodingConfig() + appCodec, legacyAmino = ecdc.Marshaler, ecdc.Amino ) diff --git a/x/auth/vesting/types/common_test.go b/x/auth/vesting/types/common_test.go index 4f361059ad3c..8e57a28c0a62 100644 --- a/x/auth/vesting/types/common_test.go +++ b/x/auth/vesting/types/common_test.go @@ -5,6 +5,6 @@ import ( ) var ( - app = simapp.Setup(false) - appCodec, _ = simapp.MakeCodecs() + app = simapp.Setup(false) + appCodec = simapp.MakeTestEncodingConfig().Marshaler ) diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index aea72006a45f..2f5c5055d2c8 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -215,7 +215,7 @@ func (suite *IntegrationTestSuite) TestSupply_MintCoins() { func (suite *IntegrationTestSuite) TestSupply_BurnCoins() { app := simapp.Setup(false) ctx := app.BaseApp.NewContext(false, tmproto.Header{Height: 1}) - appCodec, _ := simapp.MakeCodecs() + appCodec := simapp.MakeTestEncodingConfig().Marshaler // add module accounts to supply keeper maccPerms := simapp.GetMaccPerms() diff --git a/x/capability/simulation/decoder_test.go b/x/capability/simulation/decoder_test.go index 911580505944..51232b810ab7 100644 --- a/x/capability/simulation/decoder_test.go +++ b/x/capability/simulation/decoder_test.go @@ -14,7 +14,7 @@ import ( ) func TestDecodeStore(t *testing.T) { - cdc, _ := simapp.MakeCodecs() + cdc := simapp.MakeTestEncodingConfig().Marshaler dec := simulation.NewDecodeStore(cdc) capOwners := types.CapabilityOwners{ diff --git a/x/distribution/simulation/decoder_test.go b/x/distribution/simulation/decoder_test.go index 7a705f97da10..1032550acb10 100644 --- a/x/distribution/simulation/decoder_test.go +++ b/x/distribution/simulation/decoder_test.go @@ -22,7 +22,7 @@ var ( ) func TestDecodeDistributionStore(t *testing.T) { - cdc, _ := simapp.MakeCodecs() + cdc := simapp.MakeTestEncodingConfig().Marshaler dec := simulation.NewDecodeStore(cdc) decCoins := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, sdk.OneDec())} diff --git a/x/evidence/keeper/querier_test.go b/x/evidence/keeper/querier_test.go index 58a1ff81bb3e..40a9f94e5fb0 100644 --- a/x/evidence/keeper/querier_test.go +++ b/x/evidence/keeper/querier_test.go @@ -18,12 +18,12 @@ const ( func (suite *KeeperTestSuite) TestQuerier_QueryEvidence_Existing() { ctx := suite.ctx.WithIsCheckTx(false) numEvidence := 100 - _, cdc := simapp.MakeCodecs() + legacyCdc := simapp.MakeTestEncodingConfig().Amino evidence := suite.populateEvidence(ctx, numEvidence) query := abci.RequestQuery{ Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryEvidence}, "/"), - Data: cdc.MustMarshalJSON(types.NewQueryEvidenceRequest(evidence[0].Hash())), + Data: legacyCdc.MustMarshalJSON(types.NewQueryEvidenceRequest(evidence[0].Hash())), } bz, err := suite.querier(ctx, []string{types.QueryEvidence}, query) @@ -31,13 +31,13 @@ func (suite *KeeperTestSuite) TestQuerier_QueryEvidence_Existing() { suite.NotNil(bz) var e exported.Evidence - suite.Nil(cdc.UnmarshalJSON(bz, &e)) + suite.Nil(legacyCdc.UnmarshalJSON(bz, &e)) suite.Equal(evidence[0], e) } func (suite *KeeperTestSuite) TestQuerier_QueryEvidence_NonExisting() { ctx := suite.ctx.WithIsCheckTx(false) - cdc, _ := simapp.MakeCodecs() + cdc := simapp.MakeTestEncodingConfig().Marshaler numEvidence := 100 suite.populateEvidence(ctx, numEvidence) @@ -53,7 +53,7 @@ func (suite *KeeperTestSuite) TestQuerier_QueryEvidence_NonExisting() { func (suite *KeeperTestSuite) TestQuerier_QueryAllEvidence() { ctx := suite.ctx.WithIsCheckTx(false) - _, cdc := simapp.MakeCodecs() + cdc := simapp.MakeTestEncodingConfig().Amino numEvidence := 100 suite.populateEvidence(ctx, numEvidence) @@ -73,7 +73,7 @@ func (suite *KeeperTestSuite) TestQuerier_QueryAllEvidence() { func (suite *KeeperTestSuite) TestQuerier_QueryAllEvidence_InvalidPagination() { ctx := suite.ctx.WithIsCheckTx(false) - _, cdc := simapp.MakeCodecs() + cdc := simapp.MakeTestEncodingConfig().Amino numEvidence := 100 suite.populateEvidence(ctx, numEvidence) diff --git a/x/gov/keeper/common_test.go b/x/gov/keeper/common_test.go index 7ba9c5827f87..c7516eb69773 100644 --- a/x/gov/keeper/common_test.go +++ b/x/gov/keeper/common_test.go @@ -21,10 +21,10 @@ func createValidators(t *testing.T, ctx sdk.Context, app *simapp.SimApp, powers addrs := simapp.AddTestAddrsIncremental(app, ctx, 5, sdk.NewInt(30000000)) valAddrs := simapp.ConvertAddrsToValAddrs(addrs) pks := simapp.CreateTestPubKeys(5) + cdc := simapp.MakeTestEncodingConfig().Marshaler - appCodec, _ := simapp.MakeCodecs() app.StakingKeeper = stakingkeeper.NewKeeper( - appCodec, + cdc, app.GetKey(stakingtypes.StoreKey), app.AccountKeeper, app.BankKeeper, diff --git a/x/gov/simulation/decoder_test.go b/x/gov/simulation/decoder_test.go index 7a5b0fc1bc9d..6160cdfa9f70 100644 --- a/x/gov/simulation/decoder_test.go +++ b/x/gov/simulation/decoder_test.go @@ -22,11 +22,10 @@ var ( ) func TestDecodeStore(t *testing.T) { - cdc, _ := simapp.MakeCodecs() + cdc := simapp.MakeTestEncodingConfig().Marshaler dec := simulation.NewDecodeStore(cdc) endTime := time.Now().UTC() - content := types.ContentFromProposalType("test", "test", types.ProposalTypeText) proposal, err := types.NewProposal(content, 1, endTime, endTime.Add(24*time.Hour)) require.NoError(t, err) diff --git a/x/mint/simulation/decoder_test.go b/x/mint/simulation/decoder_test.go index 762768c07eaa..0116108b4ed3 100644 --- a/x/mint/simulation/decoder_test.go +++ b/x/mint/simulation/decoder_test.go @@ -14,7 +14,7 @@ import ( ) func TestDecodeStore(t *testing.T) { - cdc, _ := simapp.MakeCodecs() + cdc := simapp.MakeTestEncodingConfig().Marshaler dec := simulation.NewDecodeStore(cdc) minter := types.NewMinter(sdk.OneDec(), sdk.NewDec(15)) diff --git a/x/slashing/simulation/decoder_test.go b/x/slashing/simulation/decoder_test.go index e6122f0e0a98..32fb3f077408 100644 --- a/x/slashing/simulation/decoder_test.go +++ b/x/slashing/simulation/decoder_test.go @@ -25,7 +25,7 @@ var ( ) func TestDecodeStore(t *testing.T) { - cdc, _ := simapp.MakeCodecs() + cdc := simapp.MakeTestEncodingConfig().Marshaler dec := simulation.NewDecodeStore(cdc) info := types.NewValidatorSigningInfo(consAddr1, 0, 1, time.Now().UTC(), false, 0) diff --git a/x/staking/keeper/grpc_query_test.go b/x/staking/keeper/grpc_query_test.go index acf6f9cb5bfb..aa3b341b0953 100644 --- a/x/staking/keeper/grpc_query_test.go +++ b/x/staking/keeper/grpc_query_test.go @@ -732,10 +732,9 @@ func createValidators(t *testing.T, ctx sdk.Context, app *simapp.SimApp, powers addrs := simapp.AddTestAddrsIncremental(app, ctx, 5, sdk.TokensFromConsensusPower(300)) valAddrs := simapp.ConvertAddrsToValAddrs(addrs) pks := simapp.CreateTestPubKeys(5) - - appCodec, _ := simapp.MakeCodecs() + cdc := simapp.MakeTestEncodingConfig().Marshaler app.StakingKeeper = keeper.NewKeeper( - appCodec, + cdc, app.GetKey(types.StoreKey), app.AccountKeeper, app.BankKeeper, diff --git a/x/staking/simulation/decoder_test.go b/x/staking/simulation/decoder_test.go index 60210fa89b37..36b7404fb282 100644 --- a/x/staking/simulation/decoder_test.go +++ b/x/staking/simulation/decoder_test.go @@ -32,9 +32,8 @@ func makeTestCodec() (cdc *codec.LegacyAmino) { } func TestDecodeStore(t *testing.T) { - cdc, _ := simapp.MakeCodecs() + cdc := simapp.MakeTestEncodingConfig().Marshaler dec := simulation.NewDecodeStore(cdc) - bondTime := time.Now().UTC() val, err := types.NewValidator(valAddr1, delPk1, types.NewDescription("test", "test", "test", "test", "test")) From 51e7e913fb47f8aaccaac13732aff4b786d0ddd6 Mon Sep 17 00:00:00 2001 From: MD Aleem <72057206+aleem1314@users.noreply.github.com> Date: Fri, 8 Jan 2021 15:22:33 +0530 Subject: [PATCH 016/152] fix GET /upgrade/current query (#8280) * fix cli queries * fix codec issue * revert cli Co-authored-by: SaReN --- x/upgrade/client/rest/query.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/upgrade/client/rest/query.go b/x/upgrade/client/rest/query.go index 946430634eff..299f7f7d8f96 100644 --- a/x/upgrade/client/rest/query.go +++ b/x/upgrade/client/rest/query.go @@ -34,7 +34,7 @@ func getCurrentPlanHandler(clientCtx client.Context) func(http.ResponseWriter, * } var plan types.Plan - err = clientCtx.LegacyAmino.UnmarshalBinaryBare(res, &plan) + err = clientCtx.LegacyAmino.UnmarshalJSON(res, &plan) if rest.CheckInternalServerError(w, err) { return } From 2e8f5e52bd06a665db6b5993bda7fb13fd8c2336 Mon Sep 17 00:00:00 2001 From: MD Aleem <72057206+aleem1314@users.noreply.github.com> Date: Fri, 8 Jan 2021 17:18:04 +0530 Subject: [PATCH 017/152] [docs] x/mint - general audit and cleanup (#8267) * update docs * update docs * review changes Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- x/mint/spec/02_state.md | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/x/mint/spec/02_state.md b/x/mint/spec/02_state.md index c4d7a3eff185..1f9eae344754 100644 --- a/x/mint/spec/02_state.md +++ b/x/mint/spec/02_state.md @@ -8,28 +8,14 @@ order: 2 The minter is a space for holding current inflation information. - - Minter: `0x00 -> amino(minter)` + - Minter: `0x00 -> ProtocolBuffer(minter)` -```go -type Minter struct { - Inflation sdk.Dec // current annual inflation rate - AnnualProvisions sdk.Dec // current annual exptected provisions -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc7/proto/cosmos/mint/v1beta1/mint.proto#L8-L19 ## Params Minting params are held in the global params store. - - Params: `mint/params -> amino(params)` - -```go -type Params struct { - MintDenom string // type of coin to mint - InflationRateChange sdk.Dec // maximum annual change in inflation rate - InflationMax sdk.Dec // maximum inflation rate - InflationMin sdk.Dec // minimum inflation rate - GoalBonded sdk.Dec // goal of percent bonded atoms - BlocksPerYear uint64 // expected blocks per year -} -``` + - Params: `mint/params -> legacy_amino(params)` + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc7/proto/cosmos/mint/v1beta1/mint.proto#L21-L53 \ No newline at end of file From 0df0626604bf4b5ed2a7dd8204bb10b9e3f9d920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Fri, 8 Jan 2021 14:00:07 +0100 Subject: [PATCH 018/152] Generic 02-client cli cmds, removes light client specific ones (#8259) * remove old light client cli cmds and replace with generic ones housed in client * remove print and add client cli getter cmds * use any as arguments * revert back to single pub key * fix tests * typo * remove todo * add upgrade cli cmd cc @AdityaSripal * register upgrade cmd --- x/auth/client/rest/rest_test.go | 20 +- x/ibc/core/02-client/client/cli/cli.go | 20 ++ x/ibc/core/02-client/client/cli/query.go | 6 +- x/ibc/core/02-client/client/cli/tx.go | 246 +++++++++++++++ x/ibc/core/02-client/module.go | 5 + x/ibc/core/client/cli/cli.go | 5 +- .../06-solomachine/client/cli/cli.go | 27 -- .../06-solomachine/client/cli/tx.go | 169 ----------- x/ibc/light-clients/06-solomachine/module.go | 8 - .../06-solomachine/types/misbehaviour.go | 4 +- .../07-tendermint/client/cli/cli.go | 25 -- .../07-tendermint/client/cli/tx.go | 281 ------------------ x/ibc/light-clients/07-tendermint/module.go | 8 - 13 files changed, 290 insertions(+), 534 deletions(-) create mode 100644 x/ibc/core/02-client/client/cli/tx.go delete mode 100644 x/ibc/light-clients/06-solomachine/client/cli/cli.go delete mode 100644 x/ibc/light-clients/06-solomachine/client/cli/tx.go delete mode 100644 x/ibc/light-clients/07-tendermint/client/cli/cli.go delete mode 100644 x/ibc/light-clients/07-tendermint/client/cli/tx.go diff --git a/x/auth/client/rest/rest_test.go b/x/auth/client/rest/rest_test.go index e20874f6e716..d485467249a5 100644 --- a/x/auth/client/rest/rest_test.go +++ b/x/auth/client/rest/rest_test.go @@ -25,8 +25,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" "github.com/cosmos/cosmos-sdk/x/bank/types" + ibcclientcli "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/client/cli" ibccli "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/client/cli" - ibcsolomachinecli "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/client/cli" ) type IntegrationTestSuite struct { @@ -480,10 +480,20 @@ func (s *IntegrationTestSuite) testQueryIBCTx(txRes sdk.TxResponse, cmd *cobra.C func (s *IntegrationTestSuite) TestLegacyRestErrMessages() { val := s.network.Validators[0] + // Write client state json to temp file, used for an IBC message. + // Generated by printing the result of cdc.MarshalIntefaceJSON on + // a solo machine client state + clientStateJSON := testutil.WriteToNewTempFile( + s.T(), + `{"@type":"/ibc.lightclients.solomachine.v1.ClientState","sequence":"1","frozen_sequence":"0","consensus_state":{"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"testing","timestamp":"10"},"allow_update_after_proposal":false}`, + ) + // Write consensus json to temp file, used for an IBC message. + // Generated by printing the result of cdc.MarshalIntefaceJSON on + // a solo machine consensus state consensusJSON := testutil.WriteToNewTempFile( s.T(), - `{"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A/3SXL2ONYaOkxpdR5P8tHTlSlPv1AwQwSFxKRee5JQW"},"diversifier":"diversifier","timestamp":"10"}`, + `{"@type":"/ibc.lightclients.solomachine.v1.ConsensusState","public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"testing","timestamp":"10"}`, ) testCases := []struct { @@ -509,10 +519,10 @@ func (s *IntegrationTestSuite) TestLegacyRestErrMessages() { }, { "Successful IBC message", - ibcsolomachinecli.NewCreateClientCmd(), + ibcclientcli.NewCreateClientCmd(), []string{ - "1", // dummy sequence - consensusJSON.Name(), // path to consensus json, + clientStateJSON.Name(), // path to client state json + consensusJSON.Name(), // path to consensus json, fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), diff --git a/x/ibc/core/02-client/client/cli/cli.go b/x/ibc/core/02-client/client/cli/cli.go index 375d8f63693c..33c991521582 100644 --- a/x/ibc/core/02-client/client/cli/cli.go +++ b/x/ibc/core/02-client/client/cli/cli.go @@ -29,3 +29,23 @@ func GetQueryCmd() *cobra.Command { return queryCmd } + +// NewTxCmd returns the command to create and handle IBC clients +func NewTxCmd() *cobra.Command { + txCmd := &cobra.Command{ + Use: types.SubModuleName, + Short: "IBC client transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + txCmd.AddCommand( + NewCreateClientCmd(), + NewUpdateClientCmd(), + NewSubmitMisbehaviourCmd(), + NewUpgradeClientCmd(), + ) + + return txCmd +} diff --git a/x/ibc/core/02-client/client/cli/query.go b/x/ibc/core/02-client/client/cli/query.go index a1e9b45d22cf..7c49b12e0220 100644 --- a/x/ibc/core/02-client/client/cli/query.go +++ b/x/ibc/core/02-client/client/cli/query.go @@ -193,12 +193,11 @@ func GetCmdQueryHeader() *cobra.Command { if err != nil { return err } - header, height, err := utils.QueryTendermintHeader(clientCtx) + header, _, err := utils.QueryTendermintHeader(clientCtx) if err != nil { return err } - clientCtx = clientCtx.WithHeight(height) return clientCtx.PrintProto(&header) }, } @@ -222,12 +221,11 @@ func GetCmdNodeConsensusState() *cobra.Command { if err != nil { return err } - state, height, err := utils.QueryNodeConsensusState(clientCtx) + state, _, err := utils.QueryNodeConsensusState(clientCtx) if err != nil { return err } - clientCtx = clientCtx.WithHeight(height) return clientCtx.PrintProto(state) }, } diff --git a/x/ibc/core/02-client/client/cli/tx.go b/x/ibc/core/02-client/client/cli/tx.go new file mode 100644 index 000000000000..d036a5766d84 --- /dev/null +++ b/x/ibc/core/02-client/client/cli/tx.go @@ -0,0 +1,246 @@ +package cli + +import ( + "fmt" + "io/ioutil" + + "github.com/pkg/errors" + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/version" + "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" + "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" +) + +// NewCreateClientCmd defines the command to create a new IBC light client. +func NewCreateClientCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "create [path/to/client_state.json] [path/to/consensus_state.json]", + Short: "create new IBC client", + Long: `create a new IBC client with the specified client state and consensus state + - ClientState JSON example: {"@type":"/ibc.lightclients.solomachine.v1.ClientState","sequence":"1","frozen_sequence":"0","consensus_state":{"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"testing","timestamp":"10"},"allow_update_after_proposal":false} + - ConsensusState JSON example: {"@type":"/ibc.lightclients.solomachine.v1.ConsensusState","public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"testing","timestamp":"10"}`, + Example: fmt.Sprintf("%s tx ibc %s create [path/to/client_state.json] [path/to/consensus_state.json] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) + + // attempt to unmarshal client state argument + var clientState exported.ClientState + clientContentOrFileName := args[0] + if err := cdc.UnmarshalInterfaceJSON([]byte(clientContentOrFileName), &clientState); err != nil { + + // check for file path if JSON input is not provided + contents, err := ioutil.ReadFile(clientContentOrFileName) + if err != nil { + return errors.Wrap(err, "neither JSON input nor path to .json file for client state were provided") + } + + if err := cdc.UnmarshalInterfaceJSON(contents, &clientState); err != nil { + return errors.Wrap(err, "error unmarshalling client state file") + } + } + + // attempt to unmarshal consensus state argument + var consensusState exported.ConsensusState + consensusContentOrFileName := args[1] + if err := cdc.UnmarshalInterfaceJSON([]byte(consensusContentOrFileName), &consensusState); err != nil { + + // check for file path if JSON input is not provided + contents, err := ioutil.ReadFile(consensusContentOrFileName) + if err != nil { + return errors.Wrap(err, "neither JSON input nor path to .json file for consensus state were provided") + } + + if err := cdc.UnmarshalInterfaceJSON(contents, &consensusState); err != nil { + return errors.Wrap(err, "error unmarshalling consensus state file") + } + } + + msg, err := types.NewMsgCreateClient(clientState, consensusState, clientCtx.GetFromAddress()) + if err != nil { + return err + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// NewUpdateClientCmd defines the command to update an IBC client. +func NewUpdateClientCmd() *cobra.Command { + return &cobra.Command{ + Use: "update [client-id] [path/to/header.json]", + Short: "update existing client with a header", + Long: "update existing client with a header", + Example: fmt.Sprintf("%s tx ibc %s update [client-id] [path/to/header.json] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + clientID := args[0] + + cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) + + var header exported.Header + headerContentOrFileName := args[1] + if err := cdc.UnmarshalInterfaceJSON([]byte(headerContentOrFileName), &header); err != nil { + + // check for file path if JSON input is not provided + contents, err := ioutil.ReadFile(headerContentOrFileName) + if err != nil { + return errors.Wrap(err, "neither JSON input nor path to .json file for header were provided") + } + + if err := cdc.UnmarshalInterfaceJSON(contents, &header); err != nil { + return errors.Wrap(err, "error unmarshalling header file") + } + } + + msg, err := types.NewMsgUpdateClient(clientID, header, clientCtx.GetFromAddress()) + if err != nil { + return err + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } +} + +// NewSubmitMisbehaviourCmd defines the command to submit a misbehaviour to prevent +// future updates. +func NewSubmitMisbehaviourCmd() *cobra.Command { + return &cobra.Command{ + Use: "misbehaviour [path/to/misbehaviour.json]", + Short: "submit a client misbehaviour", + Long: "submit a client misbehaviour to prevent future updates", + Example: fmt.Sprintf("%s tx ibc %s misbehaviour [path/to/misbehaviour.json] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) + + var misbehaviour exported.Misbehaviour + misbehaviourContentOrFileName := args[0] + if err := cdc.UnmarshalInterfaceJSON([]byte(misbehaviourContentOrFileName), &misbehaviour); err != nil { + + // check for file path if JSON input is not provided + contents, err := ioutil.ReadFile(misbehaviourContentOrFileName) + if err != nil { + return errors.Wrap(err, "neither JSON input nor path to .json file for misbehaviour were provided") + } + + if err := cdc.UnmarshalInterfaceJSON(contents, misbehaviour); err != nil { + return errors.Wrap(err, "error unmarshalling misbehaviour file") + } + } + + msg, err := types.NewMsgSubmitMisbehaviour(misbehaviour.GetClientID(), misbehaviour, clientCtx.GetFromAddress()) + if err != nil { + return err + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } +} + +// NewUpgradeClientCmd defines the command to upgrade an IBC light client. +func NewUpgradeClientCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "upgrade [client-identifier] [path/to/client_state.json] [path/to/consensus_state.json] [upgrade-client-proof] [upgrade-consensus-state-proof]", + Short: "upgrade an IBC client", + Long: `upgrade the IBC client associated with the provided client identifier while providing proof committed by the counterparty chain to the new client and consensus states + - ClientState JSON example: {"@type":"/ibc.lightclients.solomachine.v1.ClientState","sequence":"1","frozen_sequence":"0","consensus_state":{"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"testing","timestamp":"10"},"allow_update_after_proposal":false} + - ConsensusState JSON example: {"@type":"/ibc.lightclients.solomachine.v1.ConsensusState","public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"testing","timestamp":"10"}`, + Example: fmt.Sprintf("%s tx ibc %s upgrade [client-identifier] [path/to/client_state.json] [path/to/consensus_state.json] [client-state-proof] [consensus-state-proof] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName), + Args: cobra.ExactArgs(5), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) + clientID := args[0] + + // attempt to unmarshal client state argument + var clientState exported.ClientState + clientContentOrFileName := args[1] + if err := cdc.UnmarshalInterfaceJSON([]byte(clientContentOrFileName), &clientState); err != nil { + + // check for file path if JSON input is not provided + contents, err := ioutil.ReadFile(clientContentOrFileName) + if err != nil { + return errors.Wrap(err, "neither JSON input nor path to .json file for client state were provided") + } + + if err := cdc.UnmarshalInterfaceJSON(contents, &clientState); err != nil { + return errors.Wrap(err, "error unmarshalling client state file") + } + } + + // attempt to unmarshal consensus state argument + var consensusState exported.ConsensusState + consensusContentOrFileName := args[2] + if err := cdc.UnmarshalInterfaceJSON([]byte(consensusContentOrFileName), &consensusState); err != nil { + + // check for file path if JSON input is not provided + contents, err := ioutil.ReadFile(consensusContentOrFileName) + if err != nil { + return errors.Wrap(err, "neither JSON input nor path to .json file for consensus state were provided") + } + + if err := cdc.UnmarshalInterfaceJSON(contents, &consensusState); err != nil { + return errors.Wrap(err, "error unmarshalling consensus state file") + } + } + + proofUpgradeClient := []byte(args[3]) + proofUpgradeConsensus := []byte(args[4]) + + msg, err := types.NewMsgUpgradeClient(clientID, clientState, consensusState, proofUpgradeClient, proofUpgradeConsensus, clientCtx.GetFromAddress()) + if err != nil { + return err + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/ibc/core/02-client/module.go b/x/ibc/core/02-client/module.go index 9a051ba1abcf..08efee8b1adc 100644 --- a/x/ibc/core/02-client/module.go +++ b/x/ibc/core/02-client/module.go @@ -18,6 +18,11 @@ func GetQueryCmd() *cobra.Command { return cli.GetQueryCmd() } +// GetTxCmd returns the root tx command for 02-client. +func GetTxCmd() *cobra.Command { + return cli.NewTxCmd() +} + // RegisterQueryService registers the gRPC query service for IBC client. func RegisterQueryService(server grpc.Server, queryServer types.QueryServer) { types.RegisterQueryServer(server, queryServer) diff --git a/x/ibc/core/client/cli/cli.go b/x/ibc/core/client/cli/cli.go index 51bb063a6a0b..bda4123be0ec 100644 --- a/x/ibc/core/client/cli/cli.go +++ b/x/ibc/core/client/cli/cli.go @@ -8,8 +8,6 @@ import ( connection "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection" channel "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel" host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - solomachine "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint" ) // GetTxCmd returns the transaction commands for this module @@ -23,8 +21,7 @@ func GetTxCmd() *cobra.Command { } ibcTxCmd.AddCommand( - solomachine.GetTxCmd(), - tendermint.GetTxCmd(), + ibcclient.GetTxCmd(), connection.GetTxCmd(), channel.GetTxCmd(), ) diff --git a/x/ibc/light-clients/06-solomachine/client/cli/cli.go b/x/ibc/light-clients/06-solomachine/client/cli/cli.go deleted file mode 100644 index ab44926204f1..000000000000 --- a/x/ibc/light-clients/06-solomachine/client/cli/cli.go +++ /dev/null @@ -1,27 +0,0 @@ -package cli - -import ( - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" -) - -// NewTxCmd returns a root CLI command handler for all solo machine transaction commands. -func NewTxCmd() *cobra.Command { - txCmd := &cobra.Command{ - Use: types.SubModuleName, - Short: "Solo Machine transaction subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - RunE: client.ValidateCmd, - } - - txCmd.AddCommand( - NewCreateClientCmd(), - NewUpdateClientCmd(), - NewSubmitMisbehaviourCmd(), - ) - - return txCmd -} diff --git a/x/ibc/light-clients/06-solomachine/client/cli/tx.go b/x/ibc/light-clients/06-solomachine/client/cli/tx.go deleted file mode 100644 index dea2d2ae7388..000000000000 --- a/x/ibc/light-clients/06-solomachine/client/cli/tx.go +++ /dev/null @@ -1,169 +0,0 @@ -package cli - -import ( - "fmt" - "io/ioutil" - "strconv" - - "github.com/pkg/errors" - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/tx" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/version" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" -) - -const ( - flagAllowUpdateAfterProposal = "allow_update_after_proposal" -) - -// NewCreateClientCmd defines the command to create a new solo machine client. -func NewCreateClientCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "create [sequence] [path/to/consensus_state.json]", - Short: "create new solo machine client", - Long: `create a new solo machine client with the specified identifier and public key - - ConsensusState json example: {"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A/3SXL2ONYaOkxpdR5P8tHTlSlPv1AwQwSFxKRee5JQW"},"diversifier":"diversifier","timestamp":"10"}`, - Example: fmt.Sprintf("%s tx ibc %s create [sequence] [path/to/consensus_state] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName), - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - sequence, err := strconv.ParseUint(args[0], 10, 64) - if err != nil { - return err - } - - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - // attempt to unmarshal consensus state argument - consensusState := &types.ConsensusState{} - if err := cdc.UnmarshalJSON([]byte(args[1]), consensusState); err != nil { - - // check for file path if JSON input is not provided - contents, err := ioutil.ReadFile(args[1]) - if err != nil { - return errors.Wrap(err, "neither JSON input nor path to .json file for consensus state were provided") - } - - if err := cdc.UnmarshalJSON(contents, consensusState); err != nil { - return errors.Wrap(err, "error unmarshalling consensus state file") - } - } - - allowUpdateAfterProposal, _ := cmd.Flags().GetBool(flagAllowUpdateAfterProposal) - - clientState := types.NewClientState(sequence, consensusState, allowUpdateAfterProposal) - msg, err := clienttypes.NewMsgCreateClient(clientState, consensusState, clientCtx.GetFromAddress()) - if err != nil { - return err - } - - if err := msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } - - cmd.Flags().Bool(flagAllowUpdateAfterProposal, false, "allow governance proposal to update client") - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -// NewUpdateClientCmd defines the command to update a solo machine client. -func NewUpdateClientCmd() *cobra.Command { - return &cobra.Command{ - Use: "update [client-id] [path/to/header.json]", - Short: "update existing client with a header", - Long: "update existing client with a solo machine header", - Example: fmt.Sprintf("%s tx ibc %s update [client-id] [path/to/header.json] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName), - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - clientID := args[0] - - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - header := &types.Header{} - if err := cdc.UnmarshalJSON([]byte(args[1]), header); err != nil { - - // check for file path if JSON input is not provided - contents, err := ioutil.ReadFile(args[1]) - if err != nil { - return errors.Wrap(err, "neither JSON input nor path to .json file for header were provided") - } - - if err := cdc.UnmarshalJSON(contents, header); err != nil { - return errors.Wrap(err, "error unmarshalling header file") - } - } - - msg, err := clienttypes.NewMsgUpdateClient(clientID, header, clientCtx.GetFromAddress()) - if err != nil { - return err - } - - if err := msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } -} - -// NewSubmitMisbehaviourCmd defines the command to submit a misbehaviour to prevent -// future updates. -func NewSubmitMisbehaviourCmd() *cobra.Command { - return &cobra.Command{ - Use: "misbehaviour [path/to/misbehaviour.json]", - Short: "submit a client misbehaviour", - Long: "submit a client misbehaviour to prevent future updates", - Example: fmt.Sprintf("%s tx ibc %s misbehaviour [path/to/misbehaviour.json] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName), - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - m := &types.Misbehaviour{} - if err := cdc.UnmarshalJSON([]byte(args[0]), m); err != nil { - - // check for file path if JSON input is not provided - contents, err := ioutil.ReadFile(args[0]) - if err != nil { - return errors.Wrap(err, "neither JSON input nor path to .json file for misbehaviour were provided") - } - - if err := cdc.UnmarshalJSON(contents, m); err != nil { - return errors.Wrap(err, "error unmarshalling misbehaviour file") - } - } - - msg, err := clienttypes.NewMsgSubmitMisbehaviour(m.ClientId, m, clientCtx.GetFromAddress()) - if err != nil { - return err - } - - if err := msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } -} diff --git a/x/ibc/light-clients/06-solomachine/module.go b/x/ibc/light-clients/06-solomachine/module.go index bdc7d9c04838..bafbd0152f1c 100644 --- a/x/ibc/light-clients/06-solomachine/module.go +++ b/x/ibc/light-clients/06-solomachine/module.go @@ -1,9 +1,6 @@ package solomachine import ( - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/client/cli" "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" ) @@ -11,8 +8,3 @@ import ( func Name() string { return types.SubModuleName } - -// GetTxCmd returns the root tx command for the solo machine client. -func GetTxCmd() *cobra.Command { - return cli.NewTxCmd() -} diff --git a/x/ibc/light-clients/06-solomachine/types/misbehaviour.go b/x/ibc/light-clients/06-solomachine/types/misbehaviour.go index 65b8a4ee4753..f5b218ccf208 100644 --- a/x/ibc/light-clients/06-solomachine/types/misbehaviour.go +++ b/x/ibc/light-clients/06-solomachine/types/misbehaviour.go @@ -9,9 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ) -var ( - _ exported.Misbehaviour = (*Misbehaviour)(nil) -) +var _ exported.Misbehaviour = &Misbehaviour{} // ClientType is a Solo Machine light client. func (misbehaviour Misbehaviour) ClientType() string { diff --git a/x/ibc/light-clients/07-tendermint/client/cli/cli.go b/x/ibc/light-clients/07-tendermint/client/cli/cli.go deleted file mode 100644 index a214869d089e..000000000000 --- a/x/ibc/light-clients/07-tendermint/client/cli/cli.go +++ /dev/null @@ -1,25 +0,0 @@ -package cli - -import ( - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" -) - -// NewTxCmd returns a root CLI command handler for all x/ibc/light-clients/07-tendermint transaction commands. -func NewTxCmd() *cobra.Command { - txCmd := &cobra.Command{ - Use: types.SubModuleName, - Short: "Tendermint client transaction subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - } - - txCmd.AddCommand( - NewCreateClientCmd(), - NewUpdateClientCmd(), - NewSubmitMisbehaviourCmd(), - ) - - return txCmd -} diff --git a/x/ibc/light-clients/07-tendermint/client/cli/tx.go b/x/ibc/light-clients/07-tendermint/client/cli/tx.go deleted file mode 100644 index f8b925e4f0cc..000000000000 --- a/x/ibc/light-clients/07-tendermint/client/cli/tx.go +++ /dev/null @@ -1,281 +0,0 @@ -package cli - -import ( - "fmt" - "io/ioutil" - "strconv" - "strings" - "time" - - ics23 "github.com/confio/ics23/go" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/tendermint/tendermint/light" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/tx" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/version" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" -) - -const ( - flagTrustLevel = "trust-level" - flagProofSpecs = "proof-specs" - flagUpgradePath = "upgrade-path" - flagAllowUpdateAfterExpiry = "allow_update_after_expiry" - flagAllowUpdateAfterMisbehaviour = "allow_update_after_misbehaviour" -) - -// NewCreateClientCmd defines the command to create a new IBC Client as defined -// in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#create -func NewCreateClientCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "create [path/to/consensus_state.json] [trusting_period] [unbonding_period] [max_clock_drift]", - Short: "create new tendermint client", - Long: `Create a new tendermint IBC client. - - 'trust-level' flag can be a fraction (eg: '1/3') or 'default' - - 'proof-specs' flag can be JSON input, a path to a .json file or 'default' - - 'upgrade-path' flag is a string specifying the upgrade path for this chain where a future upgraded client will be stored. The path is a comma-separated list representing the keys in order of the keyPath to the committed upgraded client. - e.g. 'upgrade/upgradedClient'`, - Example: fmt.Sprintf("%s tx ibc %s create [path/to/consensus_state.json] [trusting_period] [unbonding_period] [max_clock_drift] --trust-level default --consensus-params [path/to/consensus-params.json] --proof-specs [path/to/proof-specs.json] --upgrade-path upgrade/upgradedClient --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName), - Args: cobra.ExactArgs(4), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - legacyAmino := codec.NewLegacyAmino() - - var header *types.Header - if err := cdc.UnmarshalJSON([]byte(args[0]), header); err != nil { - // check for file path if JSON input is not provided - contents, err := ioutil.ReadFile(args[0]) - if err != nil { - return errors.New("neither JSON input nor path to .json file were provided for consensus header") - } - if err := cdc.UnmarshalJSON(contents, header); err != nil { - return errors.Wrap(err, "error unmarshalling consensus header file") - } - } - - var ( - trustLevel types.Fraction - specs []*ics23.ProofSpec - ) - - lvl, _ := cmd.Flags().GetString(flagTrustLevel) - - if lvl == "default" { - trustLevel = types.NewFractionFromTm(light.DefaultTrustLevel) - } else { - trustLevel, err = parseFraction(lvl) - if err != nil { - return err - } - } - - trustingPeriod, err := time.ParseDuration(args[1]) - if err != nil { - return err - } - - ubdPeriod, err := time.ParseDuration(args[2]) - if err != nil { - return err - } - - maxClockDrift, err := time.ParseDuration(args[3]) - if err != nil { - return err - } - - spc, _ := cmd.Flags().GetString(flagProofSpecs) - if spc == "default" { - specs = commitmenttypes.GetSDKSpecs() - // TODO migrate to use JSONMarshaler (implement MarshalJSONArray - // or wrap lists of proto.Message in some other message) - } else if err := legacyAmino.UnmarshalJSON([]byte(spc), &specs); err != nil { - // check for file path if JSON input not provided - contents, err := ioutil.ReadFile(spc) - if err != nil { - return errors.New("neither JSON input nor path to .json file was provided for proof specs flag") - } - // TODO migrate to use JSONMarshaler (implement MarshalJSONArray - // or wrap lists of proto.Message in some other message) - if err := legacyAmino.UnmarshalJSON(contents, &specs); err != nil { - return errors.Wrap(err, "error unmarshalling proof specs file") - } - } - - allowUpdateAfterExpiry, _ := cmd.Flags().GetBool(flagAllowUpdateAfterExpiry) - allowUpdateAfterMisbehaviour, _ := cmd.Flags().GetBool(flagAllowUpdateAfterMisbehaviour) - - upgradePathStr, _ := cmd.Flags().GetString(flagUpgradePath) - upgradePath := strings.Split(upgradePathStr, ",") - - // validate header - if err := header.ValidateBasic(); err != nil { - return err - } - - height := header.GetHeight().(clienttypes.Height) - - clientState := types.NewClientState( - header.GetHeader().GetChainID(), trustLevel, trustingPeriod, ubdPeriod, maxClockDrift, - height, specs, upgradePath, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, - ) - - consensusState := header.ConsensusState() - - msg, err := clienttypes.NewMsgCreateClient( - clientState, consensusState, clientCtx.GetFromAddress(), - ) - if err != nil { - return err - } - - if err := msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } - - cmd.Flags().String(flagTrustLevel, "default", "light client trust level fraction for header updates") - cmd.Flags().String(flagProofSpecs, "default", "proof specs format to be used for verification") - cmd.Flags().Bool(flagAllowUpdateAfterExpiry, false, "allow governance proposal to update client after expiry") - cmd.Flags().Bool(flagAllowUpdateAfterMisbehaviour, false, "allow governance proposal to update client after misbehaviour") - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -// NewUpdateClientCmd defines the command to update a client as defined in -// https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#update -func NewUpdateClientCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "update [client-id] [path/to/header.json]", - Short: "update existing client with a header", - Long: "update existing tendermint client with a tendermint header", - Example: fmt.Sprintf( - "$ %s tx ibc %s update [client-id] [path/to/header.json] --from node0 --home ../node0/cli --chain-id $CID", - version.AppName, types.SubModuleName, - ), - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - clientID := args[0] - - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - var header *types.Header - if err := cdc.UnmarshalJSON([]byte(args[1]), header); err != nil { - // check for file path if JSON input is not provided - contents, err := ioutil.ReadFile(args[1]) - if err != nil { - return errors.New("neither JSON input nor path to .json file were provided") - } - if err := cdc.UnmarshalJSON(contents, header); err != nil { - return errors.Wrap(err, "error unmarshalling header file") - } - } - - msg, err := clienttypes.NewMsgUpdateClient(clientID, header, clientCtx.GetFromAddress()) - if err != nil { - return err - } - - if err := msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } - - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -// NewSubmitMisbehaviourCmd defines the command to submit a misbehaviour to invalidate -// previous state roots and prevent future updates as defined in -// https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#misbehaviour -func NewSubmitMisbehaviourCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "misbehaviour [path/to/misbehaviour.json]", - Short: "submit a client misbehaviour", - Long: "submit a client misbehaviour to invalidate to invalidate previous state roots and prevent future updates", - Example: fmt.Sprintf( - "$ %s tx ibc %s misbehaviour [path/to/misbehaviour.json] --from node0 --home ../node0/cli --chain-id $CID", - version.AppName, types.SubModuleName, - ), - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - var m *types.Misbehaviour - if err := cdc.UnmarshalJSON([]byte(args[0]), m); err != nil { - // check for file path if JSON input is not provided - contents, err := ioutil.ReadFile(args[0]) - if err != nil { - return errors.New("neither JSON input nor path to .json file were provided") - } - if err := cdc.UnmarshalJSON(contents, m); err != nil { - return errors.Wrap(err, "error unmarshalling misbehaviour file") - } - } - - msg, err := clienttypes.NewMsgSubmitMisbehaviour(m.ClientId, m, clientCtx.GetFromAddress()) - if err != nil { - return err - } - - if err := msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } - - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -func parseFraction(fraction string) (types.Fraction, error) { - fr := strings.Split(fraction, "/") - if len(fr) != 2 || fr[0] == fraction { - return types.Fraction{}, fmt.Errorf("fraction must have format 'numerator/denominator' got %s", fraction) - } - - numerator, err := strconv.ParseUint(fr[0], 10, 64) - if err != nil { - return types.Fraction{}, fmt.Errorf("invalid trust-level numerator: %w", err) - } - - denominator, err := strconv.ParseUint(fr[1], 10, 64) - if err != nil { - return types.Fraction{}, fmt.Errorf("invalid trust-level denominator: %w", err) - } - - return types.Fraction{ - Numerator: numerator, - Denominator: denominator, - }, nil - -} diff --git a/x/ibc/light-clients/07-tendermint/module.go b/x/ibc/light-clients/07-tendermint/module.go index 38c7fa621b11..4c5cc2f947f4 100644 --- a/x/ibc/light-clients/07-tendermint/module.go +++ b/x/ibc/light-clients/07-tendermint/module.go @@ -1,9 +1,6 @@ package tendermint import ( - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/client/cli" "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" ) @@ -11,8 +8,3 @@ import ( func Name() string { return types.SubModuleName } - -// GetTxCmd returns the root tx command for the IBC client -func GetTxCmd() *cobra.Command { - return cli.NewTxCmd() -} From 325761846199fd8c0183d1a59db73713289e3af8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Jan 2021 13:41:03 +0000 Subject: [PATCH 019/152] build(deps): bump github.com/armon/go-metrics from 0.3.5 to 0.3.6 (#8273) * build(deps): bump github.com/armon/go-metrics from 0.3.5 to 0.3.6 Bumps [github.com/armon/go-metrics](https://github.com/armon/go-metrics) from 0.3.5 to 0.3.6. - [Release notes](https://github.com/armon/go-metrics/releases) - [Commits](https://github.com/armon/go-metrics/compare/v0.3.5...v0.3.6) Signed-off-by: dependabot[bot] * go.sum Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Federico Kunze --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 042dbaab52c7..c08a8f94b5cc 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ module github.com/cosmos/cosmos-sdk require ( github.com/99designs/keyring v1.1.6 github.com/DataDog/zstd v1.4.5 // indirect - github.com/armon/go-metrics v0.3.5 + github.com/armon/go-metrics v0.3.6 github.com/bgentry/speakeasy v0.1.0 github.com/btcsuite/btcd v0.21.0-beta github.com/btcsuite/btcutil v1.0.2 diff --git a/go.sum b/go.sum index 1ad018d60d49..b9231e178ea5 100644 --- a/go.sum +++ b/go.sum @@ -44,8 +44,8 @@ github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.3.5 h1:uq4txK6NAUvLQ60rotN+K+JuTnf3XP4TdQmcs9ma5mk= -github.com/armon/go-metrics v0.3.5/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-metrics v0.3.6 h1:x/tmtOF9cDBoXH7XoAGOz2qqm1DknFD1590XmD/DUJ8= +github.com/armon/go-metrics v0.3.6/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= From 5113effd24ce8b15df6cc42de6a1a8ce3a197566 Mon Sep 17 00:00:00 2001 From: Cory Date: Sat, 9 Jan 2021 03:59:07 -0800 Subject: [PATCH 020/152] v0.40.0 Changelog backport & docs publish (#8285) * Stargate Release PR -- v0.40.0 Final (#8284) * v0.40.0 final changelog & release notes * Trigger Build * update docs/versions to render v0.40 docs site --- CHANGELOG.md | 304 +++++++++++++++++--------------------------------- docs/versions | 1 + 2 files changed, 101 insertions(+), 204 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 524a4661a523..fe247044e3c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,201 +36,11 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] -## [v0.40.0-rc7](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0-rc7) - 2020-01-07 - -### Improvements - -- (tendermint) [\#8281](https://github.com/cosmos/cosmos-sdk/pull/8281) Update tendermint to v0.34.1 - -### Bug Fixes - -- (x/gentx) [\#8255](https://github.com/cosmos/cosmos-sdk/pull/8255) Fix gentx command setting wrong amount - -## [v0.40.0-rc6](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0-rc6) - 2020-01-04 - -### Improvements - -- (x/staking) [\#8178](https://github.com/cosmos/cosmos-sdk/pull/8178) Update default historical header number for stargate - -### Bug Fixes - -- (x/distribution) [\#8240](https://github.com/cosmos/cosmos-sdk/pull/8240) fix setting withdraw address in x/distribution -- (x/gentx) [\#8183](https://github.com/cosmos/cosmos-sdk/pull/8183) change gentx cmd amount to arg from flag -- (x/ibc) [\#8165](https://github.com/cosmos/cosmos-sdk/pull/8165) Support IBC upgrade on same revision -- (x/ibc) [\#8169](https://github.com/cosmos/cosmos-sdk/pull/8169) fix IBC software upgrade proposals from automatically failing, add unpackinterfaces function -- (x/ibc) [\#8170](https://github.com/cosmos/cosmos-sdk/pull/8170) fix ClientUpdateProposal unpacker -- (x/ibc) [\#8187](https://github.com/cosmos/cosmos-sdk/pull/8187) fix IBC upgrade, issue with commit & halting logic -- (x/ibc) [\#8200](https://github.com/cosmos/cosmos-sdk/pull/8200) fix IBC timeout verification bug -- (rest) [\#8221](https://github.com/cosmos/cosmos-sdk/pull/8221) fix unregistered interface failure when calling GET /blocks/latest via REST API - -## [v0.40.0-rc5](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0-rc5) - 2020-12-14 - -### Improvements - -* (auth/tx) Add new auth/tx gRPC & gRPC-Gateway endpoints for basic querying & broadcasting support - * [\#7842](https://github.com/cosmos/cosmos-sdk/pull/7842) Add TxsByEvent gRPC endpoint - * [\#7852](https://github.com/cosmos/cosmos-sdk/pull/7852) Add tx broadcast gRPC endpoint -* (client/keys) [\#8043](https://github.com/cosmos/cosmos-sdk/pull/8043) Add support for export of unarmored private key -* (client/tx) [\#7801](https://github.com/cosmos/cosmos-sdk/pull/7801) Update sign-batch multisig to work online -* (crypto) [\#7987](https://github.com/cosmos/cosmos-sdk/pull/7987) Fix the inconsistency of CryptoCdc, only use - `codec/legacy.Cdc`. -* (logging) [\#8072](https://github.com/cosmos/cosmos-sdk/pull/8072) Refactor logging: - * Use [zerolog](https://github.com/rs/zerolog) over Tendermint's go-kit logging wrapper. - * Introduce Tendermint's `--log_format=plain|json` flag. Using format `json` allows for emitting structured JSON - logs which can be consumed by an external logging facility (e.g. Loggly). Both formats log to STDERR. - * The existing `--log_level` flag and it's default value now solely relates to the global logging - level (e.g. `info`, `debug`, etc...) instead of `:`. -* (SDK) [\#7925](https://github.com/cosmos/cosmos-sdk/pull/7925) Updated dependencies - * Updated gRPC dependency to v1.33.2 - * Updated iavl dependency to v0.15-rc5 - * Updated tendermint dependency to v0.34.0 -* (version) [\#7848](https://github.com/cosmos/cosmos-sdk/pull/7848) [\#7941](https://github.com/cosmos/cosmos-sdk/pull/7941) - `version --long` output now shows the list of build dependencies and replaced build dependencies. -* (x/genutil) [\#8099](https://github.com/cosmos/cosmos-sdk/pull/8099) `init` now supports a `--recover` flag to recover - the private validator key from a given mnemonic - -### Client Breaking - -* (crypto) [\#7419](https://github.com/cosmos/cosmos-sdk/pull/7419) The SDK doesn't use Tendermint's `crypto.PubKey` - interface anymore, and uses instead it's own `PubKey` interface, defined in `crypto/types`. Replace all instances of - `crypto.PubKey` by `cryptotypes.Pubkey`. -* (x/staking) [\#7419](https://github.com/cosmos/cosmos-sdk/pull/7419) The `TmConsPubKey` method on ValidatorI has been - removed and replaced instead by `ConsPubKey` (which returns a SDK `cryptotypes.PubKey`) and `TmConsPublicKey` (which - returns a Tendermint proto PublicKey). - -### State Machine Breaking Changes - -* (x/staking) [\#7979](https://github.com/cosmos/cosmos-sdk/pull/7979) keeper pubkey storage serialization migration - from bech32 to protobuf. - -### Features -* (codec/types) [\#8106](https://github.com/cosmos/cosmos-sdk/pull/8106) Adding `NewAnyWithCustomTypeURL` to correctly - marshal Messages in TxBuilder. - -### API Breaking - -* [\#8080](https://github.com/cosmos/cosmos-sdk/pull/8080) Updated the `codec.Marshaler` interface - * Moved `MarshalAny` and `UnmarshalAny` helper functions to `codec.Marshaler` and renamed to `MarshalInterface` and - `UnmarshalInterface` respectively. These functions must take interface as a parameter (not a concrete type nor `Any` - object). Underneath they use `Any` wrapping for correct protobuf serialization. -* (client) [\#8107](https://github.com/cosmos/cosmos-sdk/pull/8107) Renamed `PrintOutput` and `PrintOutputLegacy` - methods of the `context.Client` object to `PrintProto` and `PrintObjectLegacy`. -* (grpc/tmservice) [\#8060](https://github.com/cosmos/cosmos-sdk/pull/8060) TmService gRPC service's validator pubkey - type changed from bech32 format to `Any` -* (x/auth/tx) [\#8106](https://github.com/cosmos/cosmos-sdk/pull/8106) change related to missing append functionality in - client transaction signing - + added `overwriteSig` argument to `x/auth/client.SignTx` and `client/tx.Sign` functions. - + removed `x/auth/tx.go:wrapper.GetSignatures`. The `wrapper` provides `TxBuilder` functionality, and it's a private - structure. That function was not used at all and it's not exposed through the `TxBuilder` interface. -* [\#8245](https://github.com/cosmos/cosmos-sdk/pull/8245) Removed `simapp.MakeCodecs` and use `simapp.MakeTestEncodingConfig` instead. - - -### Bug Fixes - -* (crypto) [\#7966](https://github.com/cosmos/cosmos-sdk/issues/7966) `Bip44Params` `String()` function now correctly - returns the absolute HD path by adding the `m/` prefix. -* (crypto/keys) [\#7838](https://github.com/cosmos/cosmos-sdk/pull/7838) Add support for TM secp256k1 keys back to the - SDK for consensus pubkeys -* (x/auth/client/cli) [\#8106](https://github.com/cosmos/cosmos-sdk/pull/8106) fixing regression bugs in transaction signing. - -## [v0.40.0-rc4](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0-rc4) - 2020-11-30 - -### Bug Fixes - -* (store) [#8048](https://github.com/cosmos/cosmos-sdk/pull/8048) Fix issue where `SetInitialVersion` was never getting called, causing all queries to return empty on chains with non-zero initial height - -## [v0.40.0-rc3](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0-rc3) - 2020-11-06 - -### Improvements - -* (tendermint) [\#7828](https://github.com/cosmos/cosmos-sdk/pull/7828) Update tendermint dependency to v0.34.0-rc6 - -## [v0.40.0-rc2](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0-rc2) - 2020-11-02 - -### Client Breaking - -* (x/upgrade) [#7697](https://github.com/cosmos/cosmos-sdk/pull/7697) Rename flag name "--time" to "--upgrade-time", "--info" to "--upgrade-info", to keep it consistent with help message. -* (x/auth) [#7788](https://github.com/cosmos/cosmos-sdk/pull/7788) Remove `tx auth` subcommands, all auth subcommands exist as `tx ` - -### API Breaking - -* (x/staking/types) [\#7447](https://github.com/cosmos/cosmos-sdk/issues/7447) Remove bech32 PubKey support: - * `ValidatorI` interface update. `GetConsPubKey` renamed to `TmConsPubKey` (consensus public key must be a tendermint key). `TmConsPubKey`, `GetConsAddr` methods return error. - * `Validator` update. Methods changed in `ValidatorI` (as described above) and `ToTmValidator` return error. - * `Validator.ConsensusPubkey` type changed from `string` to `codectypes.Any`. - * `MsgCreateValidator.Pubkey` type changed from `string` to `codectypes.Any`. -* Deprecating and renaming `MakeEncodingConfig` to `MakeTestEncodingConfig` (both in `simapp` and `simapp/params` packages). -* (tx) [\#7688](https://github.com/cosmos/cosmos-sdk/pull/7688) The gRPC simulate service method has been moved from `cosmos.base.v1beta1.simulate` to `cosmos.tx.v1beta1`, as a method in the Tx service. -* [#7764](https://github.com/cosmos/cosmos-sdk/pull/7764) Added module initialization options: - * `server/types.AppExporter` requires extra argument: `AppOptions`. - * `server.AddCommands` requires extra argument: `addStartFlags types.ModuleInitFlags` - * `x/crisis.NewAppModule` has a new attribute: `skipGenesisInvariants`. [PR](https://github.com/cosmos/cosmos-sdk/pull/7764) -* [#7918](https://github.com/cosmos/cosmos-sdk/pull/7918) Add x/capability safety checks: - * All outward facing APIs will now check that capability is not nil and name is not empty before performing any state-machine changes - * `SetIndex` has been renamed to `InitializeIndex` - - -### Features - -* (tx) [\#7688](https://github.com/cosmos/cosmos-sdk/pull/7688) Add a new Tx gRPC service with methods `Simulate` and `GetTx` (by hash). -* __Modules__ - * `x/crisis` has a new function: `AddModuleInitFlags`, which will register optional crisis module flags for the start command. - -### Bug Fixes - -* (client) [\#7699](https://github.com/cosmos/cosmos-sdk/pull/7699) Fix panic in context when setting invalid nodeURI. `WithNodeURI` does not set the `Client` in the context. -* (x/gov) [#7641](https://github.com/cosmos/cosmos-sdk/pull/7641) Fix tally calculation precision error. - -### Improvements - -* (rest) [#7649](https://github.com/cosmos/cosmos-sdk/pull/7649) Return an unsigned tx in legacy GET /tx endpoint when signature conversion fails -* (cli) [#7764](https://github.com/cosmos/cosmos-sdk/pull/7764) Update x/banking and x/crisis InitChain to improve node startup time - -## [v0.40.0-rc1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0-rc1) - 2020-10-19 - -### Client Breaking Changes - -* __Modules__ - * (x/staking) [\#7499](https://github.com/cosmos/cosmos-sdk/pull/7499) `BondStatus` is now a protobuf `enum` instead - of an `int32`, and JSON serialized using its protobuf name, so expect names like `BOND_STATUS_UNBONDING` as opposed - to `Unbonding`. - * (x/staking) [\#7556](https://github.com/cosmos/cosmos-sdk/pull/7556) The ABCI's `Result.Data` field for - `MsgBeginRedelegate` and `MsgUndelegate` responses does not contain custom binary marshaled `completionTime`, but the - protobuf encoded `MsgBeginRedelegateResponse` and `MsgUndelegateResponse` structs respectively - * (x/evidence) [\#7538](https://github.com/cosmos/cosmos-sdk/pull/7538) The ABCI's `Result.Data` field for - `MsgSubmitEvidence` responses does not contain the raw evidence's hash, but the protobuf encoded - `MsgSubmitEvidenceResponse` struct. - * (x/gov) [\#7533](https://github.com/cosmos/cosmos-sdk/pull/7533) The ABCI's `Result.Data` field for - `MsgSubmitProposal` responses does not contain a raw binary encoding of the `proposalID`, but the protobuf encoded - `MsgSubmitSubmitProposalResponse` struct. - -### API Breaking - -* (AppModule) [\#7518](https://github.com/cosmos/cosmos-sdk/pull/7518) [\#7584](https://github.com/cosmos/cosmos-sdk/pull/7584) Rename `AppModule.RegisterQueryServices` to `AppModule.RegisterServices`, as this method now registers multiple services (the gRPC query service and the protobuf Msg service). A `Configurator` struct is used to hold the different services. - -### Features - -* (modules) [\#7540](https://github.com/cosmos/cosmos-sdk/issues/7540) Protobuf service definitions can now be used for -packing `Msg`s in transactions as defined in [ADR 031](./docs/architecture/adr-031-msg-service.md). All modules now -define a `Msg` protobuf service. -* (codec) [\#7519](https://github.com/cosmos/cosmos-sdk/pull/7519) `InterfaceRegistry` now inherits `jsonpb.AnyResolver`, and has a `RegisterCustomTypeURL` method to support ADR 031 packing of `Any`s. `AnyResolver` is now a required parameter to `RejectUnknownFields`. -* (baseapp) [\#7519](https://github.com/cosmos/cosmos-sdk/pull/7519) Add `ServiceMsgRouter` to BaseApp to handle routing of protobuf service `Msg`s. The two new types defined in ADR 031, `sdk.ServiceMsg` and `sdk.MsgRequest` are introduced with this router. -* (cli) [\#7221](https://github.com/cosmos/cosmos-sdk/pull/7221) Add the option of emitting amino encoded json from the CLI - -### Bug Fixes - -* (kvstore) [\#7415](https://github.com/cosmos/cosmos-sdk/pull/7415) Allow new stores to be registered during on-chain upgrades. -* (rest) [\#7730](https://github.com/cosmos/cosmos-sdk/pull/7730) Fix fetch txs by height on legacy REST endpoint - -### Improvements - -* (tendermint) [\#7527](https://github.com/cosmos/cosmos-sdk/pull/7527) Update sdk to tendermint 0.34-rc5 -* (iavl) [\#7549](https://github.com/cosmos/cosmos-sdk/pull/7549) Update sdk to IAVL 0.15.0-rc4 - -## [v0.40.0-rc0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0-rc0) - 2020-10-13 +## [v0.40.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0) - 2021-01-08 v0.40.0, known as the Stargate release of the Cosmos SDK, is one of the largest releases -of the Cosmos SDK since launch. Please read through this changelog and [release notes](./RELEASE_NOTES.md) to make sure you are aware of any relevant breaking changes. +of the Cosmos SDK since launch. Please read through this changelog and [release notes](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/RELEASE_NOTES.md) to make +sure you are aware of any relevant breaking changes. ### Client Breaking Changes @@ -238,8 +48,10 @@ of the Cosmos SDK since launch. Please read through this changelog and [release * (client/keys) [\#5889](https://github.com/cosmos/cosmos-sdk/pull/5889) remove `keys update` command. * (x/auth) [\#5844](https://github.com/cosmos/cosmos-sdk/pull/5844) `tx sign` command now returns an error when signing is attempted with offline/multisig keys. * (x/auth) [\#6108](https://github.com/cosmos/cosmos-sdk/pull/6108) `tx sign` command's `--validate-signatures` flag is migrated into a `tx validate-signatures` standalone command. + * (x/auth) [#7788](https://github.com/cosmos/cosmos-sdk/pull/7788) Remove `tx auth` subcommands, all auth subcommands exist as `tx ` * (x/genutil) [\#6651](https://github.com/cosmos/cosmos-sdk/pull/6651) The `gentx` command has been improved. No longer are `--from` and `--name` flags required. Instead, a single argument, `name`, is required which refers to the key pair in the Keyring. In addition, an optional `--moniker` flag can be provided to override the moniker found in `config.toml`. + * (x/upgrade) [#7697](https://github.com/cosmos/cosmos-sdk/pull/7697) Rename flag name "--time" to "--upgrade-time", "--info" to "--upgrade-info", to keep it consistent with help message. * __REST / Queriers__ * (api) [\#6426](https://github.com/cosmos/cosmos-sdk/pull/6426) The ability to start an out-of-process API REST server has now been removed. Instead, the API server is now started in-process along with the application and Tendermint. Configuration options have been added to `app.toml` to enable/disable the API server along with additional HTTP server options. * (client) [\#7246](https://github.com/cosmos/cosmos-sdk/pull/7246) The rest server endpoint `/swagger-ui/` is replaced by `/swagger/`, and contains swagger documentation for gRPC Gateway routes in addition to legacy REST routes. Swagger API is exposed only if set in `app.toml`. @@ -250,6 +62,9 @@ of the Cosmos SDK since launch. Please read through this changelog and [release * __General__ * (baseapp) [\#6384](https://github.com/cosmos/cosmos-sdk/pull/6384) The `Result.Data` is now a Protocol Buffer encoded binary blob of type `TxData`. The `TxData` contains `Data` which contains a list of Protocol Buffer encoded message data and the corresponding message type. * (client) [\#5783](https://github.com/cosmos/cosmos-sdk/issues/5783) Unify all coins representations on JSON client requests for governance proposals. + * (crypto) [\#7419](https://github.com/cosmos/cosmos-sdk/pull/7419) The SDK doesn't use Tendermint's `crypto.PubKey` + interface anymore, and uses instead it's own `PubKey` interface, defined in `crypto/types`. Replace all instances of + `crypto.PubKey` by `cryptotypes.Pubkey`. * (store/rootmulti) [\#6390](https://github.com/cosmos/cosmos-sdk/pull/6390) Proofs of empty stores are no longer supported. * (store/types) [\#5730](https://github.com/cosmos/cosmos-sdk/pull/5730) store.types.Cp() is removed in favour of types.CopyBytes(). * (x/auth) [\#6054](https://github.com/cosmos/cosmos-sdk/pull/6054) Remove custom JSON marshaling for base accounts as multsigs cannot be bech32 decoded. @@ -257,14 +72,29 @@ of the Cosmos SDK since launch. Please read through this changelog and [release * (x/bank) [\#5785](https://github.com/cosmos/cosmos-sdk/issues/5785) In x/bank errors, JSON strings coerced to valid UTF-8 bytes at JSON marshalling time are now replaced by human-readable expressions. This change can potentially break compatibility with all those client side tools that parse log messages. + * (x/evidence) [\#7538](https://github.com/cosmos/cosmos-sdk/pull/7538) The ABCI's `Result.Data` field for + `MsgSubmitEvidence` responses does not contain the raw evidence's hash, but the protobuf encoded + `MsgSubmitEvidenceResponse` struct. + * (x/gov) [\#7533](https://github.com/cosmos/cosmos-sdk/pull/7533) The ABCI's `Result.Data` field for + `MsgSubmitProposal` responses does not contain a raw binary encoding of the `proposalID`, but the protobuf encoded + `MsgSubmitSubmitProposalResponse` struct. * (x/gov) [\#6859](https://github.com/cosmos/cosmos-sdk/pull/6859) `ProposalStatus` and `VoteOption` are now JSON serialized using its protobuf name, so expect names like `PROPOSAL_STATUS_DEPOSIT_PERIOD` as opposed to `DepositPeriod`. + * (x/staking) [\#7499](https://github.com/cosmos/cosmos-sdk/pull/7499) `BondStatus` is now a protobuf `enum` instead + of an `int32`, and JSON serialized using its protobuf name, so expect names like `BOND_STATUS_UNBONDING` as opposed + to `Unbonding`. + * (x/staking) [\#7556](https://github.com/cosmos/cosmos-sdk/pull/7556) The ABCI's `Result.Data` field for + `MsgBeginRedelegate` and `MsgUndelegate` responses does not contain custom binary marshaled `completionTime`, but the + protobuf encoded `MsgBeginRedelegateResponse` and `MsgUndelegateResponse` structs respectively ### API Breaking Changes * __Baseapp / Client__ + * (AppModule) [\#7518](https://github.com/cosmos/cosmos-sdk/pull/7518) [\#7584](https://github.com/cosmos/cosmos-sdk/pull/7584) Rename `AppModule.RegisterQueryServices` to `AppModule.RegisterServices`, as this method now registers multiple services (the gRPC query service and the protobuf Msg service). A `Configurator` struct is used to hold the different services. * (baseapp) [\#5865](https://github.com/cosmos/cosmos-sdk/pull/5865) The `SimulationResponse` returned from tx simulation is now JSON encoded instead of Amino binary. * (client) [\#6290](https://github.com/cosmos/cosmos-sdk/pull/6290) `CLIContext` is renamed to `Context`. `Context` and all related methods have been moved from package context to client. * (client) [\#6525](https://github.com/cosmos/cosmos-sdk/pull/6525) Removed support for `indent` in JSON responses. Clients should consider piping to an external tool such as `jq`. + * (client) [\#8107](https://github.com/cosmos/cosmos-sdk/pull/8107) Renamed `PrintOutput` and `PrintOutputLegacy` + methods of the `context.Client` object to `PrintProto` and `PrintObjectLegacy`. * (client/flags) [\#6632](https://github.com/cosmos/cosmos-sdk/pull/6632) Remove NewCompletionCmd(), the function is now available in tendermint. * (client/input) [\#5904](https://github.com/cosmos/cosmos-sdk/pull/5904) Removal of unnecessary `GetCheckPassword`, `PrintPrefixed` functions. * (client/keys) [\#5889](https://github.com/cosmos/cosmos-sdk/pull/5889) Rename `NewKeyBaseFromDir()` -> `NewLegacyKeyBaseFromDir()`. @@ -272,6 +102,10 @@ of the Cosmos SDK since launch. Please read through this changelog and [release * (client/rpc) [\#6290](https://github.com/cosmos/cosmos-sdk/pull/6290) `client` package and subdirs reorganization. * (client/lcd) [\#6290](https://github.com/cosmos/cosmos-sdk/pull/6290) `CliCtx` of struct `RestServer` in package client/lcd has been renamed to `ClientCtx`. * (codec) [\#6330](https://github.com/cosmos/cosmos-sdk/pull/6330) `codec.RegisterCrypto` has been moved to the `crypto/codec` package and the global `codec.Cdc` Amino instance has been deprecated and moved to the `codec/legacy_global` package. + * (codec) [\#8080](https://github.com/cosmos/cosmos-sdk/pull/8080) Updated the `codec.Marshaler` interface + * Moved `MarshalAny` and `UnmarshalAny` helper functions to `codec.Marshaler` and renamed to `MarshalInterface` and + `UnmarshalInterface` respectively. These functions must take interface as a parameter (not a concrete type nor `Any` + object). Underneath they use `Any` wrapping for correct protobuf serialization. * (crypto) [\#6780](https://github.com/cosmos/cosmos-sdk/issues/6780) Move ledger code to its own package. * (crypto/types/multisig) [\#6373](https://github.com/cosmos/cosmos-sdk/pull/6373) `multisig.Multisignature` has been renamed to `AminoMultisignature` * (codec) `*codec.LegacyAmino` is now a wrapper around Amino which provides backwards compatibility with protobuf `Any`. ALL legacy code should use `*codec.LegacyAmino` instead of `*amino.Codec` directly @@ -286,6 +120,7 @@ of the Cosmos SDK since launch. Please read through this changelog and [release information on how to implement the new `Keyring` interface. * [\#5858](https://github.com/cosmos/cosmos-sdk/pull/5858) Make Keyring store keys by name and address's hexbytes representation. * (export) [\#5952](https://github.com/cosmos/cosmos-sdk/pull/5952) `AppExporter` now returns ABCI consensus parameters to be included in marshaled exported state. These parameters must be returned from the application via the `BaseApp`. + * (simapp) Deprecating and renaming `MakeEncodingConfig` to `MakeTestEncodingConfig` (both in `simapp` and `simapp/params` packages). * (store) [\#5803](https://github.com/cosmos/cosmos-sdk/pull/5803) The `store.CommitMultiStore` interface now includes the new `snapshots.Snapshotter` interface as well. * (types) [\#5579](https://github.com/cosmos/cosmos-sdk/pull/5579) The `keepRecent` field has been removed from the `PruningOptions` type. The `PruningOptions` type now only includes fields `KeepEvery` and `SnapshotEvery`, where `KeepEvery` @@ -310,16 +145,46 @@ of the Cosmos SDK since launch. Please read through this changelog and [release * (modules) [\#6447](https://github.com/cosmos/cosmos-sdk/issues/6447) Rename `blacklistedAddrs` to `blockedAddrs`. * (modules) [\#6834](https://github.com/cosmos/cosmos-sdk/issues/6834) Add `RegisterInterfaces` method to `AppModuleBasic` to support registration of protobuf interface types. * (modules) [\#6734](https://github.com/cosmos/cosmos-sdk/issues/6834) Add `TxEncodingConfig` parameter to `AppModuleBasic.ValidateGenesis` command to support JSON tx decoding in `genutil`. + * (modules) [#7764](https://github.com/cosmos/cosmos-sdk/pull/7764) Added module initialization options: + * `server/types.AppExporter` requires extra argument: `AppOptions`. + * `server.AddCommands` requires extra argument: `addStartFlags types.ModuleInitFlags` + * `x/crisis.NewAppModule` has a new attribute: `skipGenesisInvariants`. [PR](https://github.com/cosmos/cosmos-sdk/pull/7764) * (types) [\#6327](https://github.com/cosmos/cosmos-sdk/pull/6327) `sdk.Msg` now inherits `proto.Message`, as a result all `sdk.Msg` types now use pointer semantics. * (types) [\#7032](https://github.com/cosmos/cosmos-sdk/pull/7032) All types ending with `ID` (e.g. `ProposalID`) now end with `Id` (e.g. `ProposalId`), to match default Protobuf generated format. Also see [\#7033](https://github.com/cosmos/cosmos-sdk/pull/7033) for more details. * (x/auth) [\#6029](https://github.com/cosmos/cosmos-sdk/pull/6029) Module accounts have been moved from `x/supply` to `x/auth`. * (x/auth) [\#6443](https://github.com/cosmos/cosmos-sdk/issues/6443) Move `FeeTx` and `TxWithMemo` interfaces from `x/auth/ante` to `types`. + * (x/auth) [\#7006](https://github.com/cosmos/cosmos-sdk/pull/7006) All `AccountRetriever` methods now take `client.Context` as a parameter instead of as a struct member. + * (x/auth) [\#6270](https://github.com/cosmos/cosmos-sdk/pull/6270) The passphrase argument has been removed from the signature of the following functions and methods: `BuildAndSign`, ` MakeSignature`, ` SignStdTx`, `TxBuilder.BuildAndSign`, `TxBuilder.Sign`, `TxBuilder.SignStdTx` + * (x/auth) [\#6428](https://github.com/cosmos/cosmos-sdk/issues/6428): + * `NewAnteHandler` and `NewSigVerificationDecorator` both now take a `SignModeHandler` parameter. + * `SignatureVerificationGasConsumer` now has the signature: `func(meter sdk.GasMeter, sig signing.SignatureV2, params types.Params) error`. + * The `SigVerifiableTx` interface now has a `GetSignaturesV2() ([]signing.SignatureV2, error)` method and no longer has the `GetSignBytes` method. + * (x/auth/tx) [\#8106](https://github.com/cosmos/cosmos-sdk/pull/8106) change related to missing append functionality in + client transaction signing + + added `overwriteSig` argument to `x/auth/client.SignTx` and `client/tx.Sign` functions. + + removed `x/auth/tx.go:wrapper.GetSignatures`. The `wrapper` provides `TxBuilder` functionality, and it's a private + structure. That function was not used at all and it's not exposed through the `TxBuilder` interface. * (x/bank) [\#7327](https://github.com/cosmos/cosmos-sdk/pull/7327) AddCoins and SubtractCoins no longer return a resultingValue and will only return an error. + * (x/capability) [#7918](https://github.com/cosmos/cosmos-sdk/pull/7918) Add x/capability safety checks: + * All outward facing APIs will now check that capability is not nil and name is not empty before performing any state-machine changes + * `SetIndex` has been renamed to `InitializeIndex` * (x/evidence) [\#7251](https://github.com/cosmos/cosmos-sdk/pull/7251) New evidence types and light client evidence handling. The module function names changed. + * (x/evidence) [\#5952](https://github.com/cosmos/cosmos-sdk/pull/5952) Remove APIs for getting and setting `x/evidence` parameters. `BaseApp` now uses a `ParamStore` to manage Tendermint consensus parameters which is managed via the `x/params` `Substore` type. + * (x/gov) [\#6147](https://github.com/cosmos/cosmos-sdk/pull/6147) The `Content` field on `Proposal` and `MsgSubmitProposal` + is now `Any` in concordance with [ADR 019](docs/architecture/adr-019-protobuf-state-encoding.md) and `GetContent` should now + be used to retrieve the actual proposal `Content`. Also the `NewMsgSubmitProposal` constructor now may return an `error` * (x/ibc) [\#6374](https://github.com/cosmos/cosmos-sdk/pull/6374) `VerifyMembership` and `VerifyNonMembership` now take a `specs []string` argument to specify the proof format used for verification. Most SDK chains can simply use `commitmenttypes.GetSDKSpecs()` for this argument. * (x/params) [\#5619](https://github.com/cosmos/cosmos-sdk/pull/5619) The `x/params` keeper now accepts a `codec.Marshaller` instead of a reference to an amino codec. Amino is still used for JSON serialization. * (x/staking) [\#6451](https://github.com/cosmos/cosmos-sdk/pull/6451) `DefaultParamspace` and `ParamKeyTable` in staking module are moved from keeper to types to enforce consistency. + * (x/staking) [\#7419](https://github.com/cosmos/cosmos-sdk/pull/7419) The `TmConsPubKey` method on ValidatorI has been + removed and replaced instead by `ConsPubKey` (which returns a SDK `cryptotypes.PubKey`) and `TmConsPublicKey` (which + returns a Tendermint proto PublicKey). + * (x/staking/types) [\#7447](https://github.com/cosmos/cosmos-sdk/issues/7447) Remove bech32 PubKey support: + * `ValidatorI` interface update. `GetConsPubKey` renamed to `TmConsPubKey` (consensus public key must be a tendermint key). `TmConsPubKey`, `GetConsAddr` methods return error. + * `Validator` update. Methods changed in `ValidatorI` (as described above) and `ToTmValidator` return error. + * `Validator.ConsensusPubkey` type changed from `string` to `codectypes.Any`. + * `MsgCreateValidator.Pubkey` type changed from `string` to `codectypes.Any`. * (x/supply) [\#6010](https://github.com/cosmos/cosmos-sdk/pull/6010) All `x/supply` types and APIs have been moved to `x/bank`. * [\#6409](https://github.com/cosmos/cosmos-sdk/pull/6409) Rename all IsEmpty methods to Empty across the codebase and enforce consistency. * [\#6231](https://github.com/cosmos/cosmos-sdk/pull/6231) Simplify `AppModule` interface, `Route` and `NewHandler` methods become only `Route` @@ -327,16 +192,7 @@ of the Cosmos SDK since launch. Please read through this changelog and [release * (x/slashing) [\#6212](https://github.com/cosmos/cosmos-sdk/pull/6212) Remove `Get*` prefixes from key construction functions * (server) [\#6079](https://github.com/cosmos/cosmos-sdk/pull/6079) Remove `UpgradeOldPrivValFile` (deprecated in Tendermint Core v0.28). * [\#5719](https://github.com/cosmos/cosmos-sdk/pull/5719) Bump Go requirement to 1.14+ - * (x/evidence) [\#5952](https://github.com/cosmos/cosmos-sdk/pull/5952) Remove APIs for getting and setting `x/evidence` parameters. `BaseApp` now uses a `ParamStore` to manage Tendermint consensus parameters which is managed via the `x/params` `Substore` type. - * (x/gov) [\#6147](https://github.com/cosmos/cosmos-sdk/pull/6147) The `Content` field on `Proposal` and `MsgSubmitProposal` - is now `Any` in concordance with [ADR 019](docs/architecture/adr-019-protobuf-state-encoding.md) and `GetContent` should now - be used to retrieve the actual proposal `Content`. Also the `NewMsgSubmitProposal` constructor now may return an `error` - * (x/auth) [\#7006](https://github.com/cosmos/cosmos-sdk/pull/7006) All `AccountRetriever` methods now take `client.Context` as a parameter instead of as a struct member. - * (x/auth) [\#6270](https://github.com/cosmos/cosmos-sdk/pull/6270) The passphrase argument has been removed from the signature of the following functions and methods: `BuildAndSign`, ` MakeSignature`, ` SignStdTx`, `TxBuilder.BuildAndSign`, `TxBuilder.Sign`, `TxBuilder.SignStdTx` - * (x/auth) [\#6428](https://github.com/cosmos/cosmos-sdk/issues/6428): - * `NewAnteHandler` and `NewSigVerificationDecorator` both now take a `SignModeHandler` parameter. - * `SignatureVerificationGasConsumer` now has the signature: `func(meter sdk.GasMeter, sig signing.SignatureV2, params types.Params) error`. - * The `SigVerifiableTx` interface now has a `GetSignaturesV2() ([]signing.SignatureV2, error)` method and no longer has the `GetSignBytes` method. + ### State Machine Breaking @@ -405,6 +261,8 @@ of the Cosmos SDK since launch. Please read through this changelog and [release * Every reference of `crypto.Pubkey` in context of a `Validator` is now of type string. `GetPubKeyFromBech32` must be used to get the `crypto.Pubkey`. * The `Keeper` constructor now takes a `codec.Marshaler` instead of a concrete Amino codec. This exact type provided is specified by `ModuleCdc`. + * (x/staking) [\#7979](https://github.com/cosmos/cosmos-sdk/pull/7979) keeper pubkey storage serialization migration + from bech32 to protobuf. * (x/supply) [\#6010](https://github.com/cosmos/cosmos-sdk/pull/6010) Removed the `x/supply` module by merging the existing types and APIs into the `x/bank` module. * (x/supply) [\#5533](https://github.com/cosmos/cosmos-sdk/pull/5533) Migrate the `x/supply` module to use Protocol Buffers for state serialization instead of Amino. @@ -424,8 +282,11 @@ of the Cosmos SDK since launch. Please read through this changelog and [release * (x/auth) [\#6213](https://github.com/cosmos/cosmos-sdk/issues/6213) Introduce new protobuf based path for transaction signing, see [ADR020](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-020-protobuf-transaction-encoding.md) for more details * (x/auth) [\#6350](https://github.com/cosmos/cosmos-sdk/pull/6350) New sign-batch command to sign StdTx batch files. * (baseapp) [\#5803](https://github.com/cosmos/cosmos-sdk/pull/5803) Added support for taking state snapshots at regular height intervals, via options `snapshot-interval` and `snapshot-keep-recent`. + * (baseapp) [\#7519](https://github.com/cosmos/cosmos-sdk/pull/7519) Add `ServiceMsgRouter` to BaseApp to handle routing of protobuf service `Msg`s. The two new types defined in ADR 031, `sdk.ServiceMsg` and `sdk.MsgRequest` are introduced with this router. * (client) [\#5921](https://github.com/cosmos/cosmos-sdk/issues/5921) Introduce new gRPC and gRPC Gateway based APIs for querying app & module data. See [ADR021](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-021-protobuf-query-encoding.md) for more details * (cli) [\#7485](https://github.com/cosmos/cosmos-sdk/pull/7485) Introduce a new optional `--keyring-dir` flag that allows clients to specify a Keyring directory if it does not reside in the directory specified by `--home`. + * (cli) [\#7221](https://github.com/cosmos/cosmos-sdk/pull/7221) Add the option of emitting amino encoded json from the CLI + * (codec) [\#7519](https://github.com/cosmos/cosmos-sdk/pull/7519) `InterfaceRegistry` now inherits `jsonpb.AnyResolver`, and has a `RegisterCustomTypeURL` method to support ADR 031 packing of `Any`s. `AnyResolver` is now a required parameter to `RejectUnknownFields`. * (coin) [\#6755](https://github.com/cosmos/cosmos-sdk/pull/6755) Add custom regex validation for `Coin` denom by overwriting `CoinDenomRegex` when using `/types/coin.go`. * (config) [\#7265](https://github.com/cosmos/cosmos-sdk/pull/7265) Support Tendermint block pruning through a new `min-retain-blocks` configuration that can be set in either `app.toml` or via the CLI. This parameter is used in conjunction with other criteria to determine the height at which Tendermint should prune blocks. * (events) [\#7121](https://github.com/cosmos/cosmos-sdk/pull/7121) The application now derives what events are indexed by Tendermint via the `index-events` configuration in `app.toml`, which is a list of events taking the form `{eventType}.{attributeKey}`. @@ -434,7 +295,13 @@ of the Cosmos SDK since launch. Please read through this changelog and [release * (genesis) [\#7089](https://github.com/cosmos/cosmos-sdk/pull/7089) The `export` command now adds a `initial_height` field in the exported JSON. Baseapp's `CommitMultiStore` now also has a `SetInitialVersion` setter, so it can set the initial store version inside `InitChain` and start a new chain from a given height. * __General__ * (crypto/multisig) [\#6241](https://github.com/cosmos/cosmos-sdk/pull/6241) Add Multisig type directly to the repo. Previously this was in tendermint. + * (codec/types) [\#8106](https://github.com/cosmos/cosmos-sdk/pull/8106) Adding `NewAnyWithCustomTypeURL` to correctly + marshal Messages in TxBuilder. * (tests) [\#6489](https://github.com/cosmos/cosmos-sdk/pull/6489) Introduce package `testutil`, new in-process testing network framework for use in integration and unit tests. + * (tx) Add new auth/tx gRPC & gRPC-Gateway endpoints for basic querying & broadcasting support + * [\#7842](https://github.com/cosmos/cosmos-sdk/pull/7842) Add TxsByEvent gRPC endpoint + * [\#7852](https://github.com/cosmos/cosmos-sdk/pull/7852) Add tx broadcast gRPC endpoint + * (tx) [\#7688](https://github.com/cosmos/cosmos-sdk/pull/7688) Add a new Tx gRPC service with methods `Simulate` and `GetTx` (by hash). * (store) [\#5803](https://github.com/cosmos/cosmos-sdk/pull/5803) Added `rootmulti.Store` methods for taking and restoring snapshots, based on `iavl.Store` export/import. * (store) [\#6324](https://github.com/cosmos/cosmos-sdk/pull/6324) IAVL store query proofs now return CommitmentOp which wraps an ics23 CommitmentProof * (store) [\#6390](https://github.com/cosmos/cosmos-sdk/pull/6390) `RootMulti` store query proofs now return `CommitmentOp` which wraps `CommitmentProofs` @@ -442,8 +309,12 @@ of the Cosmos SDK since launch. Please read through this changelog and [release * `ProofRuntime` only decodes and verifies `ics23.CommitmentProof` * __Modules__ * (modules) [\#5921](https://github.com/cosmos/cosmos-sdk/issues/5921) Introduction of Query gRPC service definitions along with REST annotations for gRPC Gateway for each module + * (modules) [\#7540](https://github.com/cosmos/cosmos-sdk/issues/7540) Protobuf service definitions can now be used for + packing `Msg`s in transactions as defined in [ADR 031](./docs/architecture/adr-031-msg-service.md). All modules now + define a `Msg` protobuf service. * (x/auth/vesting) [\#7209](https://github.com/cosmos/cosmos-sdk/pull/7209) Create new `MsgCreateVestingAccount` message type along with CLI handler that allows for the creation of delayed and continuous vesting types. * (x/capability) [\#5828](https://github.com/cosmos/cosmos-sdk/pull/5828) Capability module integration as outlined in [ADR 3 - Dynamic Capability Store](https://github.com/cosmos/tree/master/docs/architecture/adr-003-dynamic-capability-store.md). + * (x/crisis) `x/crisis` has a new function: `AddModuleInitFlags`, which will register optional crisis module flags for the start command. * (x/ibc) [\#5277](https://github.com/cosmos/cosmos-sdk/pull/5277) `x/ibc` changes from IBC alpha. For more details check the the [`x/ibc/core/spec`](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/core/spec) directory, or the ICS specs below: * [ICS 002 - Client Semantics](https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics) subpackage * [ICS 003 - Connection Semantics](https://github.com/cosmos/ics/blob/master/spec/ics-003-connection-semantics) subpackage @@ -463,10 +334,14 @@ of the Cosmos SDK since launch. Please read through this changelog and [release * __Baseapp / Client / REST__ * (client) [\#5964](https://github.com/cosmos/cosmos-sdk/issues/5964) `--trust-node` is now false by default - for real. Users must ensure it is set to true if they don't want to enable the verifier. * (client) [\#6402](https://github.com/cosmos/cosmos-sdk/issues/6402) Fix `keys add` `--algo` flag which only worked for Tendermint's `secp256k1` default key signing algorithm. + * (client) [\#7699](https://github.com/cosmos/cosmos-sdk/pull/7699) Fix panic in context when setting invalid nodeURI. `WithNodeURI` does not set the `Client` in the context. * (export) [\#6510](https://github.com/cosmos/cosmos-sdk/pull/6510/) Field TimeIotaMs now is included in genesis file while exporting. * (rest) [\#5906](https://github.com/cosmos/cosmos-sdk/pull/5906) Fix an issue that make some REST calls panic when sending invalid or incomplete requests. + * (crypto) [\#7966](https://github.com/cosmos/cosmos-sdk/issues/7966) `Bip44Params` `String()` function now correctly + returns the absolute HD path by adding the `m/` prefix. * (crypto/keyring) [\#5844](https://github.com/cosmos/cosmos-sdk/pull/5844) `Keyring.Sign()` methods no longer decode amino signatures when method receivers are offline/multisig keys. + * (store) [\#7415](https://github.com/cosmos/cosmos-sdk/pull/7415) Allow new stores to be registered during on-chain upgrades. * __Modules__ * (modules) [\#5569](https://github.com/cosmos/cosmos-sdk/issues/5569) `InitGenesis`, for the relevant modules, now ensures module accounts exist. * (x/auth) [\#5892](https://github.com/cosmos/cosmos-sdk/pull/5892) Add `RegisterKeyTypeCodec` to register new @@ -474,6 +349,8 @@ of the Cosmos SDK since launch. Please read through this changelog and [release * (x/bank) [\#6536](https://github.com/cosmos/cosmos-sdk/pull/6536) Fix bug in `WriteGeneratedTxResponse` function used by multiple REST endpoints. Now it writes a Tx in StdTx format. * (x/genutil) [\#5938](https://github.com/cosmos/cosmos-sdk/pull/5938) Fix `InitializeNodeValidatorFiles` error handling. + * (x/gentx) [\#8183](https://github.com/cosmos/cosmos-sdk/pull/8183) change gentx cmd amount to arg from flag + * (x/gov) [#7641](https://github.com/cosmos/cosmos-sdk/pull/7641) Fix tally calculation precision error. * (x/staking) [\#6529](https://github.com/cosmos/cosmos-sdk/pull/6529) Export validator addresses (previously was empty). * (x/staking) [\#5949](https://github.com/cosmos/cosmos-sdk/pull/5949) Skip staking `HistoricalInfoKey` in simulations as headers are not exported. * (x/staking) [\#6061](https://github.com/cosmos/cosmos-sdk/pull/6061) Allow a validator to immediately unjail when no signing info is present due to @@ -492,8 +369,13 @@ falling below their minimum self-delegation and never having been bonded. The va internet connection. Previously, `--generate-only` served this purpose in addition to only allowing txs to be generated. Now, `--generate-only` solely allows txs to be generated without being broadcasted and disallows Keybase use and `--offline` allows the use of Keybase but does not allow any functionality that requires an online connection. + * (cli) [#7764](https://github.com/cosmos/cosmos-sdk/pull/7764) Update x/banking and x/crisis InitChain to improve node startup time * (client) [\#5856](https://github.com/cosmos/cosmos-sdk/pull/5856) Added the possibility to set `--offline` flag with config command. * (client) [\#5895](https://github.com/cosmos/cosmos-sdk/issues/5895) show config options in the config command's help screen. + * (client/keys) [\#8043](https://github.com/cosmos/cosmos-sdk/pull/8043) Add support for export of unarmored private key + * (client/tx) [\#7801](https://github.com/cosmos/cosmos-sdk/pull/7801) Update sign-batch multisig to work online + * (x/genutil) [\#8099](https://github.com/cosmos/cosmos-sdk/pull/8099) `init` now supports a `--recover` flag to recover + the private validator key from a given mnemonic * __Modules__ * (x/auth) [\#5702](https://github.com/cosmos/cosmos-sdk/pull/5702) Add parameter querying support for `x/auth`. * (x/auth/ante) [\#6040](https://github.com/cosmos/cosmos-sdk/pull/6040) `AccountKeeper` interface used for `NewAnteHandler` and handler's decorators to add support of using custom `AccountKeeper` implementations. @@ -505,11 +387,23 @@ falling below their minimum self-delegation and never having been bonded. The va * (x/staking) [\#5584](https://github.com/cosmos/cosmos-sdk/pull/5584) Add util function `ToTmValidator` that converts a `staking.Validator` type to `*tmtypes.Validator`. * (x/staking) [\#6163](https://github.com/cosmos/cosmos-sdk/pull/6163) CLI and REST call to unbonding delegations and delegations now accept pagination. + * (x/staking) [\#8178](https://github.com/cosmos/cosmos-sdk/pull/8178) Update default historical header number for stargate * __General__ - * (tendermint) [\#6365](https://github.com/cosmos/cosmos-sdk/issues/6365) Update tendermint version to v0.34, and make necessary upgrades to the SDK + * (crypto) [\#7987](https://github.com/cosmos/cosmos-sdk/pull/7987) Fix the inconsistency of CryptoCdc, only use + `codec/legacy.Cdc`. + * (logging) [\#8072](https://github.com/cosmos/cosmos-sdk/pull/8072) Refactor logging: + * Use [zerolog](https://github.com/rs/zerolog) over Tendermint's go-kit logging wrapper. + * Introduce Tendermint's `--log_format=plain|json` flag. Using format `json` allows for emitting structured JSON + logs which can be consumed by an external logging facility (e.g. Loggly). Both formats log to STDERR. + * The existing `--log_level` flag and it's default value now solely relates to the global logging + level (e.g. `info`, `debug`, etc...) instead of `:`. + * (rest) [#7649](https://github.com/cosmos/cosmos-sdk/pull/7649) Return an unsigned tx in legacy GET /tx endpoint when signature conversion fails * (simulation) [\#6002](https://github.com/cosmos/cosmos-sdk/pull/6002) Add randomized consensus params into simulation. * (store) [\#6481](https://github.com/cosmos/cosmos-sdk/pull/6481) Move `SimpleProofsFromMap` from Tendermint into the SDK. * (store) [\#6719](https://github.com/cosmos/cosmos-sdk/6754) Add validity checks to stores for nil and empty keys. + * (SDK) Updated dependencies + * Updated iavl dependency to v0.15.3 + * Update tendermint to v0.34.1 * (types) [\#7027](https://github.com/cosmos/cosmos-sdk/pull/7027) `Coin(s)` and `DecCoin(s)` updates: * Bump denomination max length to 128 * Allow uppercase letters and numbers in denominations to support [ADR 001](./docs/architecture/adr-001-coin-source-tracing.md) @@ -523,6 +417,8 @@ falling below their minimum self-delegation and never having been bonded. The va * (types) [\#6128](https://github.com/cosmos/cosmos-sdk/pull/6137) Add `String()` method to `GasMeter`. * (types) [\#6195](https://github.com/cosmos/cosmos-sdk/pull/6195) Add codespace to broadcast(sync/async) response. * (types) \#6897 Add KV type from tendermint to `types` directory. + * (version) [\#7848](https://github.com/cosmos/cosmos-sdk/pull/7848) [\#7941](https://github.com/cosmos/cosmos-sdk/pull/7941) + `version --long` output now shows the list of build dependencies and replaced build dependencies. ## [v0.39.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.39.1) - 2020-08-11 diff --git a/docs/versions b/docs/versions index d5dc85eb286f..d4be1796400d 100644 --- a/docs/versions +++ b/docs/versions @@ -1,2 +1,3 @@ master master launchpad/backports v0.39 +release/v0.40.x v0.40 From 2c611b57064367b51b7d67ba25b85bbff1e37b9c Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Sat, 9 Jan 2021 13:08:46 +0100 Subject: [PATCH 021/152] 8058 fix zero time checks (#8282) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- x/evidence/legacy/v038/types.go | 2 +- x/evidence/types/evidence.go | 2 +- .../07-tendermint/types/consensus_state.go | 7 ++----- x/upgrade/keeper/keeper.go | 2 +- x/upgrade/legacy/v038/types.go | 9 +++++---- x/upgrade/types/plan.go | 10 +++++----- 6 files changed, 15 insertions(+), 17 deletions(-) diff --git a/x/evidence/legacy/v038/types.go b/x/evidence/legacy/v038/types.go index f438e2bec562..994f718ca5fd 100644 --- a/x/evidence/legacy/v038/types.go +++ b/x/evidence/legacy/v038/types.go @@ -91,7 +91,7 @@ func (e Equivocation) Hash() tmbytes.HexBytes { // ValidateBasic performs basic stateless validation checks on an Equivocation object. func (e Equivocation) ValidateBasic() error { - if e.Time.IsZero() { + if e.Time.Unix() <= 0 { return fmt.Errorf("invalid equivocation time: %s", e.Time) } if e.Height < 1 { diff --git a/x/evidence/types/evidence.go b/x/evidence/types/evidence.go index 8558623baa67..95705cc5b937 100644 --- a/x/evidence/types/evidence.go +++ b/x/evidence/types/evidence.go @@ -43,7 +43,7 @@ func (e *Equivocation) Hash() tmbytes.HexBytes { // ValidateBasic performs basic stateless validation checks on an Equivocation object. func (e *Equivocation) ValidateBasic() error { - if e.Time.IsZero() { + if e.Time.Unix() <= 0 { return fmt.Errorf("invalid equivocation time: %s", e.Time) } if e.Height < 1 { diff --git a/x/ibc/light-clients/07-tendermint/types/consensus_state.go b/x/ibc/light-clients/07-tendermint/types/consensus_state.go index b581983944fd..adb469a3d108 100644 --- a/x/ibc/light-clients/07-tendermint/types/consensus_state.go +++ b/x/ibc/light-clients/07-tendermint/types/consensus_state.go @@ -48,11 +48,8 @@ func (cs ConsensusState) ValidateBasic() error { if err := tmtypes.ValidateHash(cs.NextValidatorsHash); err != nil { return sdkerrors.Wrap(err, "next validators hash is invalid") } - if cs.Timestamp.IsZero() { - return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "timestamp cannot be zero Unix time") - } - if cs.Timestamp.UnixNano() < 0 { - return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "timestamp cannot be negative Unix time") + if cs.Timestamp.Unix() <= 0 { + return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "timestamp must be a positive Unix time") } return nil } diff --git a/x/upgrade/keeper/keeper.go b/x/upgrade/keeper/keeper.go index 0cf619cf36fe..1092885bcb3f 100644 --- a/x/upgrade/keeper/keeper.go +++ b/x/upgrade/keeper/keeper.go @@ -60,7 +60,7 @@ func (k Keeper) ScheduleUpgrade(ctx sdk.Context, plan types.Plan) error { return err } - if !plan.Time.IsZero() { + if plan.Time.Unix() > 0 { if !plan.Time.After(ctx.BlockHeader().Time) { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "upgrade cannot be scheduled in the past") } diff --git a/x/upgrade/legacy/v038/types.go b/x/upgrade/legacy/v038/types.go index fb06a6dc5a1c..db833477bf23 100644 --- a/x/upgrade/legacy/v038/types.go +++ b/x/upgrade/legacy/v038/types.go @@ -64,10 +64,11 @@ func (p Plan) ValidateBasic() error { if p.Height < 0 { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "height cannot be negative") } - if p.Time.IsZero() && p.Height == 0 { + isValidTime := p.Time.Unix() > 0 + if !isValidTime && p.Height == 0 { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "must set either time or height") } - if !p.Time.IsZero() && p.Height != 0 { + if isValidTime && p.Height != 0 { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "cannot set both time and height") } @@ -76,7 +77,7 @@ func (p Plan) ValidateBasic() error { // ShouldExecute returns true if the Plan is ready to execute given the current context func (p Plan) ShouldExecute(ctx sdk.Context) bool { - if !p.Time.IsZero() { + if p.Time.Unix() > 0 { return !ctx.BlockTime().Before(p.Time) } if p.Height > 0 { @@ -87,7 +88,7 @@ func (p Plan) ShouldExecute(ctx sdk.Context) bool { // DueAt is a string representation of when this plan is due to be executed func (p Plan) DueAt() string { - if !p.Time.IsZero() { + if p.Time.Unix() > 0 { return fmt.Sprintf("time: %s", p.Time.UTC().Format(time.RFC3339)) } return fmt.Sprintf("height: %d", p.Height) diff --git a/x/upgrade/types/plan.go b/x/upgrade/types/plan.go index 2cbacd60b0be..aa1a0601ffca 100644 --- a/x/upgrade/types/plan.go +++ b/x/upgrade/types/plan.go @@ -39,13 +39,13 @@ func (p Plan) ValidateBasic() error { if p.Height < 0 { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "height cannot be negative") } - if p.Time.IsZero() && p.Height == 0 { + if p.Time.Unix() <= 0 && p.Height == 0 { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "must set either time or height") } - if !p.Time.IsZero() && p.Height != 0 { + if p.Time.Unix() > 0 && p.Height != 0 { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "cannot set both time and height") } - if !p.Time.IsZero() && p.UpgradedClientState != nil { + if p.Time.Unix() > 0 && p.UpgradedClientState != nil { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "IBC chain upgrades must only set height") } @@ -54,7 +54,7 @@ func (p Plan) ValidateBasic() error { // ShouldExecute returns true if the Plan is ready to execute given the current context func (p Plan) ShouldExecute(ctx sdk.Context) bool { - if !p.Time.IsZero() { + if p.Time.Unix() > 0 { return !ctx.BlockTime().Before(p.Time) } if p.Height > 0 { @@ -65,7 +65,7 @@ func (p Plan) ShouldExecute(ctx sdk.Context) bool { // DueAt is a string representation of when this plan is due to be executed func (p Plan) DueAt() string { - if !p.Time.IsZero() { + if p.Time.Unix() > 0 { return fmt.Sprintf("time: %s", p.Time.UTC().Format(time.RFC3339)) } return fmt.Sprintf("height: %d", p.Height) From 5b0b3232ae3649595b6f005519f7e0376bd6defa Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Sun, 10 Jan 2021 00:28:56 -0500 Subject: [PATCH 022/152] remove old adr --- docs/architecture/adr-033-gov-split-vote.md | 104 -------------------- 1 file changed, 104 deletions(-) delete mode 100644 docs/architecture/adr-033-gov-split-vote.md diff --git a/docs/architecture/adr-033-gov-split-vote.md b/docs/architecture/adr-033-gov-split-vote.md deleted file mode 100644 index 759778c0c42d..000000000000 --- a/docs/architecture/adr-033-gov-split-vote.md +++ /dev/null @@ -1,104 +0,0 @@ -# ADR 033: Governance split votes - -## Changelog - -- 2020/10/28: Intial draft - -## Status - -Proposed - -## Abstract - -This ADR defines a modification to the the governance module that would allow a staker to split their votes into several voting options. For example, it could use 70% of its voting power to vote Yes and 30% of its voting power to vote No. - -## Context - -Currently, an address can cast a vote with only one options (Yes/No/Abstain/NoWithVeto) and use their full voting power behind that choice. - -However, often times the entity owning that address might not be a single individual. For example, a company might have different stakeholders who want to vote differently, and so it makes sense to allow them to split their voting power. Another example use case is exchanges. Many centralized exchanges often stake a portion of their users' tokens in their custody. Currently, it is not possible for them to do "passthrough voting" and giving their users voting rights over their tokens. However, with this system, exchanges can poll their users for voting preferences, and then vote on-chain proportionally to the results of the poll. - -## Decision - -We modify the vote structs to be - -``` -type WeightedVoteOption struct { - Option string - Weight sdk.Dec -} - -type Vote struct { - ProposalID int64 - Voter sdk.Address - Options []WeightedVoteOption -} -``` - -And for backwards compatibility, we introduce `MsgWeightedVote` while keeping `MsgVote`. -``` -type MsgVote struct { - ProposalID int64 - Voter sdk.Address - Option Option -} - -type MsgWeightedVote struct { - ProposalID int64 - Voter sdk.Address - Options []WeightedVoteOption -} -``` - -The `ValidateBasic` of a `MsgWeightedVote` struct would require that -1. The sum of all the Rates is equal to 1.0 -2. No Option is repeated - -The governance tally function will iterate over all the options in a vote and add to the tally the result of the voter's voting power * the rate for that option. - -``` -tally() { - results := map[types.VoteOption]sdk.Dec - - for _, vote := range votes { - for i, weightedOption := range vote.Options { - results[weightedOption.Option] += getVotingPower(vote.voter) * weightedOption.Weight - } - } -} -``` - -The CLI command for creating a multi-option vote would be as such: -```sh -simd tx gov vote 1 "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05" --from mykey -``` - -To create a single-option vote a user can do either -``` -simd tx gov vote 1 "yes=1" --from mykey -``` - -or - -```sh -simd tx gov vote 1 yes --from mykey -``` - -to maintain backwards compatibility. - - -## Consequences - -### Backwards Compatibility -- Previous VoteMsg types will remain the same and so clients will not have to update their procedure unless they want to support the WeightedVoteMsg feature. -- When querying a Vote struct from state, its structure will be different, and so clients wanting to display all voters and their respective votes will have to handle the new format and the fact that a single voter can have split votes. -- The result of querying the tally function should have the same API for clients. - -### Positive -- Can make the voting process more accurate for addresses representing multiple stakeholders, often some of the largest addresses. - -### Negative -- Is more complex than simple voting, and so may be harder to explain to users. However, this is mostly mitigated because the feature is opt-in. - -### Neutral -- Relatively minor change to governance tally function. From 6d2dfff877acfc78125e112006ad6d3173b53bdb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Jan 2021 10:16:17 +0000 Subject: [PATCH 023/152] build(deps): bump github.com/gogo/protobuf from 1.3.1 to 1.3.2 (#8291) Bumps [github.com/gogo/protobuf](https://github.com/gogo/protobuf) from 1.3.1 to 1.3.2. - [Release notes](https://github.com/gogo/protobuf/releases) - [Commits](https://github.com/gogo/protobuf/compare/v1.3.1...v1.3.2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index c08a8f94b5cc..185962ff44a6 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 github.com/gogo/gateway v1.1.0 - github.com/gogo/protobuf v1.3.1 + github.com/gogo/protobuf v1.3.2 github.com/golang/mock v1.4.4 github.com/golang/protobuf v1.4.3 github.com/golang/snappy v0.0.2 // indirect From 834688f6d428adc09c8a9d97c88a3fea7372c505 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Jan 2021 08:38:03 -0300 Subject: [PATCH 024/152] build(deps): bump gaurav-nelson/github-action-markdown-link-check (#8290) Bumps [gaurav-nelson/github-action-markdown-link-check](https://github.com/gaurav-nelson/github-action-markdown-link-check) from 1.0.11 to 1.0.12. - [Release notes](https://github.com/gaurav-nelson/github-action-markdown-link-check/releases) - [Commits](https://github.com/gaurav-nelson/github-action-markdown-link-check/compare/1.0.11...0fe4911067fa322422f325b002d2038ba5602170) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/linkchecker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linkchecker.yml b/.github/workflows/linkchecker.yml index d16019158c89..887e9903587f 100644 --- a/.github/workflows/linkchecker.yml +++ b/.github/workflows/linkchecker.yml @@ -7,6 +7,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@master - - uses: gaurav-nelson/github-action-markdown-link-check@1.0.11 + - uses: gaurav-nelson/github-action-markdown-link-check@1.0.12 with: folder-path: "docs" From 8ac3bd26428d0f76e914e39129a942ce5235da4f Mon Sep 17 00:00:00 2001 From: atheeshp <59333759+atheeshp@users.noreply.github.com> Date: Mon, 11 Jan 2021 17:41:22 +0530 Subject: [PATCH 025/152] x/{auth, bank, distr} docs basic cleanup (#8268) * basic code clean up * revert MsgVerifyInvariant * review changes * review changes * review changes * review changes * review changes * review changes Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- x/auth/spec/01_concepts.md | 2 +- x/auth/spec/05_vesting.md | 50 +++++++----------------- x/auth/spec/07_params.md | 10 ++--- x/bank/spec/02_keepers.md | 2 +- x/bank/spec/03_messages.md | 11 +----- x/distribution/spec/02_state.md | 24 ++++-------- x/distribution/spec/04_messages.md | 61 +++++++++--------------------- x/distribution/spec/README.md | 6 +-- 8 files changed, 51 insertions(+), 115 deletions(-) diff --git a/x/auth/spec/01_concepts.md b/x/auth/spec/01_concepts.md index 47316b4cbbf6..9f8c9b8d8f2d 100644 --- a/x/auth/spec/01_concepts.md +++ b/x/auth/spec/01_concepts.md @@ -19,7 +19,7 @@ signature verification, as well as costs proportional to the tx size. Operators should set minimum gas prices when starting their nodes. They must set the unit costs of gas in each token denomination they wish to support: -`gaiad start ... --minimum-gas-prices=0.00001stake;0.05photinos` +`simd start ... --minimum-gas-prices=0.00001stake;0.05photinos` When adding transactions to mempool or gossipping transactions, validators check if the transaction's gas prices, which are determined by the provided fees, meet diff --git a/x/auth/spec/05_vesting.md b/x/auth/spec/05_vesting.md index 50bf70d03fcf..a253f7de604b 100644 --- a/x/auth/spec/05_vesting.md +++ b/x/auth/spec/05_vesting.md @@ -88,52 +88,28 @@ type VestingAccount interface { GetStartTime() int64 GetEndTime() int64 } +``` +### BaseVestingAccount ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/vesting/v1beta1/vesting.proto#L10-L33 -// BaseVestingAccount implements the VestingAccount interface. It contains all -// the necessary fields needed for any vesting account implementation. -type BaseVestingAccount struct { - BaseAccount - - OriginalVesting Coins // coins in account upon initialization - DelegatedFree Coins // coins that are vested and delegated - DelegatedVesting Coins // coins that vesting and delegated - - EndTime int64 // when the coins become unlocked -} - -// ContinuousVestingAccount implements the VestingAccount interface. It -// continuously vests by unlocking coins linearly with respect to time. -type ContinuousVestingAccount struct { - BaseVestingAccount - - StartTime int64 // when the coins start to vest -} +### ContinuousVestingAccount ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/vesting/v1beta1/vesting.proto#L35-L43 -// DelayedVestingAccount implements the VestingAccount interface. It vests all -// coins after a specific time, but non prior. In other words, it keeps them -// locked until a specified time. -type DelayedVestingAccount struct { - BaseVestingAccount -} +### DelayedVestingAccount ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/vesting/v1beta1/vesting.proto#L45-L53 -// VestingPeriod defines a length of time and amount of coins that will vest -type Period struct { - Length int64 // length of the period, in seconds - Amount Coins // amount of coins vesting during this period -} +### Period ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/vesting/v1beta1/vesting.proto#L56-L62 +```go // Stores all vesting periods passed as part of a PeriodicVestingAccount type Periods []Period -// PeriodicVestingAccount implements the VestingAccount interface. It -// periodically vests by unlocking coins during each specified period -type PeriodicVestingAccount struct { - BaseVestingAccount - StartTime int64 - Periods Periods // the vesting schedule -} ``` +### PeriodicVestingAccount ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/vesting/v1beta1/vesting.proto#L64-L73 + In order to facilitate less ad-hoc type checking and assertions and to support flexibility in account balance usage, the existing `x/bank` `ViewKeeper` interface is updated to contain the following: diff --git a/x/auth/spec/07_params.md b/x/auth/spec/07_params.md index 93ddc89c2219..1bf24e7f6d6e 100644 --- a/x/auth/spec/07_params.md +++ b/x/auth/spec/07_params.md @@ -8,8 +8,8 @@ The auth module contains the following parameters: | Key | Type | Example | | ---------------------- | --------------- | ------- | -| MaxMemoCharacters | string (uint64) | "256" | -| TxSigLimit | string (uint64) | "7" | -| TxSizeCostPerByte | string (uint64) | "10" | -| SigVerifyCostED25519 | string (uint64) | "590" | -| SigVerifyCostSecp256k1 | string (uint64) | "1000" | +| MaxMemoCharacters | uint64 | 256 | +| TxSigLimit | uint64 | 7 | +| TxSizeCostPerByte | uint64 | 10 | +| SigVerifyCostED25519 | uint64 | 590 | +| SigVerifyCostSecp256k1 | uint64 | 1000 | diff --git a/x/bank/spec/02_keepers.md b/x/bank/spec/02_keepers.md index ec74358fbb70..0032961b1f3b 100644 --- a/x/bank/spec/02_keepers.md +++ b/x/bank/spec/02_keepers.md @@ -44,7 +44,7 @@ The base keeper provides full-permission access: the ability to arbitrary modify type Keeper interface { SendKeeper - InitGenesis(sdk.Context, types.GenesisState) + InitGenesis(sdk.Context, *types.GenesisState) ExportGenesis(sdk.Context) *types.GenesisState GetSupply(ctx sdk.Context) exported.SupplyI diff --git a/x/bank/spec/03_messages.md b/x/bank/spec/03_messages.md index ecb9dc695fae..07c42f5f78e5 100644 --- a/x/bank/spec/03_messages.md +++ b/x/bank/spec/03_messages.md @@ -6,18 +6,11 @@ order: 3 ## MsgSend -```go -// MsgSend represents a message to send coins from one account to another. -message MsgSend { - string from_address = 1; - string to_address = 2; - repeated cosmos.base.v1beta1.Coin amount = 3; -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/bank/v1beta1/tx.proto#L19-L28 `handleMsgSend` just runs `inputOutputCoins`. -``` +```go handleMsgSend(msg MsgSend) inputSum = 0 for input in inputs diff --git a/x/distribution/spec/02_state.md b/x/distribution/spec/02_state.md index 624fb9f0ff61..b8dbde4a9ae4 100644 --- a/x/distribution/spec/02_state.md +++ b/x/distribution/spec/02_state.md @@ -15,7 +15,7 @@ for fractions of coins to be received from operations like inflation. When coins are distributed from the pool they are truncated back to `sdk.Coins` which are non-decimal. -- FeePool: `0x00 -> amino(FeePool)` +- FeePool: `0x00 -> ProtocolBuffer(FeePool)` ```go // coins with decimal @@ -25,15 +25,10 @@ type DecCoin struct { Amount sdk.Dec Denom string } - -type FeePool struct { - TotalValAccumUpdateHeight int64 // last height which the total validator accum was updated - TotalValAccum sdk.Dec // total valdator accum held by validators - Pool DecCoins // funds for all validators which have yet to be withdrawn - CommunityPool DecCoins // pool for community funds yet to be spent -} ``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/distribution/v1beta1/distribution.proto#L94-L101 + ## Validator Distribution Validator distribution information for the relevant validator is updated each time: @@ -43,16 +38,13 @@ Validator distribution information for the relevant validator is updated each ti 3. any delegator withdraws from a validator, or 4. the validator withdraws it's commission. -- ValidatorDistInfo: `0x02 | ValOperatorAddr -> amino(validatorDistribution)` +- ValidatorDistInfo: `0x02 | ValOperatorAddr -> ProtocolBuffer(validatorDistribution)` ```go type ValidatorDistInfo struct { - FeePoolWithdrawalHeight int64 // last height this validator withdrew from the global fee pool - Pool DecCoins // rewards owed to delegators, commission has already been charged (includes proposer reward) - PoolCommission DecCoins // commission collected by this validator (pending withdrawal) - - TotalDelAccumUpdateHeight int64 // last height which the total delegator accum was updated - TotalDelAccum sdk.Dec // total proposer pool accumulation factor held by delegators + OperatorAddress sdk.AccAddress + SelfBondRewards sdk.DecCoins + ValidatorCommission types.ValidatorAccumulatedCommission } ``` @@ -64,7 +56,7 @@ properties change (aka bonded tokens etc.) its properties will remain constant and the delegator's _accumulation_ factor can be calculated passively knowing only the height of the last withdrawal and its current properties. -- DelegationDistInfo: `0x02 | DelegatorAddr | ValOperatorAddr -> amino(delegatorDist)` +- DelegationDistInfo: `0x02 | DelegatorAddr | ValOperatorAddr -> ProtocolBuffer(delegatorDist)` ```go type DelegationDistInfo struct { diff --git a/x/distribution/spec/04_messages.md b/x/distribution/spec/04_messages.md index ef57cb4c3106..4aff6b532317 100644 --- a/x/distribution/spec/04_messages.md +++ b/x/distribution/spec/04_messages.md @@ -4,57 +4,35 @@ order: 4 # Messages -## MsgWithdrawDelegationRewardsAll +## MsgSetWithdrawAddress -When a delegator wishes to withdraw their rewards it must send -`MsgWithdrawDelegationRewardsAll`. Note that parts of this transaction logic are also -triggered each with any change in individual delegations, such as an unbond, -redelegation, or delegation of additional tokens to a specific validator. +By default a withdrawal address is delegator address. If a delegator wants to change it's +withdrawal address it must send `MsgSetWithdrawAddress`. -```go -type MsgWithdrawDelegationRewardsAll struct { - DelegatorAddr sdk.AccAddress -} ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/distribution/v1beta1/tx.proto#L29-L37 -func WithdrawDelegationRewardsAll(delegatorAddr, withdrawAddr sdk.AccAddress) - height = GetHeight() - withdraw = GetDelegatorRewardsAll(delegatorAddr, height) - SendCoins(distributionModuleAcc, withdrawAddr, withdraw.TruncateDecimal()) +```go -func GetDelegatorRewardsAll(delegatorAddr sdk.AccAddress, height int64) DecCoins - - // get all distribution scenarios - delegations = GetDelegations(delegatorAddr) - - // collect all entitled rewards - withdraw = 0 - pool = staking.GetPool() - feePool = GetFeePool() - for delegation = range delegations - delInfo = GetDelegationDistInfo(delegation.DelegatorAddr, - delegation.ValidatorAddr) - valInfo = GetValidatorDistInfo(delegation.ValidatorAddr) - validator = GetValidator(delegation.ValidatorAddr) +func (k Keeper) SetWithdrawAddr(ctx sdk.Context, delegatorAddr sdk.AccAddress, withdrawAddr sdk.AccAddress) error + if k.blockedAddrs[withdrawAddr.String()] { + fail with "`{withdrawAddr}` is not allowed to receive external funds" + } - feePool, diWithdraw = delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens, - validator.Tokens, validator.DelegatorShares, validator.Commission) - withdraw += diWithdraw + if !k.GetWithdrawAddrEnabled(ctx) { + fail with `ErrSetWithdrawAddrDisabled` + } - SetFeePool(feePool) - return withdraw + k.SetDelegatorWithdrawAddr(ctx, delegatorAddr, withdrawAddr) ``` -## MsgWithdrawDelegationReward +## MsgWithdrawDelegatorReward under special circumstances a delegator may wish to withdraw rewards from only a single validator. -```go -type MsgWithdrawDelegationReward struct { - DelegatorAddr sdk.AccAddress - ValidatorAddr sdk.ValAddress -} ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/distribution/v1beta1/tx.proto#L42-L50 +```go func WithdrawDelegationReward(delegatorAddr, validatorAddr, withdrawAddr sdk.AccAddress) height = GetHeight() @@ -74,19 +52,16 @@ func WithdrawDelegationReward(delegatorAddr, validatorAddr, withdrawAddr sdk.Acc ``` -## MsgWithdrawValidatorRewardsAll +### Withdraw Validator Rewards All When a validator wishes to withdraw their rewards it must send -`MsgWithdrawValidatorRewardsAll`. Note that parts of this transaction logic are also +array of `MsgWithdrawDelegatorReward`. Note that parts of this transaction logic are also triggered each with any change in individual delegations, such as an unbond, redelegation, or delegation of additional tokens to a specific validator. This transaction withdraws the validators commission fee, as well as any rewards earning on their self-delegation. ```go -type MsgWithdrawValidatorRewardsAll struct { - OperatorAddr sdk.ValAddress // validator address to withdraw from -} func WithdrawValidatorRewardsAll(operatorAddr, withdrawAddr sdk.AccAddress) diff --git a/x/distribution/spec/README.md b/x/distribution/spec/README.md index 6d97f8fa3a0c..fe5f5069d63f 100644 --- a/x/distribution/spec/README.md +++ b/x/distribution/spec/README.md @@ -89,9 +89,9 @@ to set up a script to periodically withdraw and rebond rewards. 2. **[State](02_state.md)** 3. **[End Block](03_end_block.md)** 4. **[Messages](04_messages.md)** - - [MsgWithdrawDelegationRewardsAll](04_messages.md#msgwithdrawdelegationrewardsall) - - [MsgWithdrawDelegationReward](04_messages.md#msgwithdrawdelegationreward) - - [MsgWithdrawValidatorRewardsAll](04_messages.md#msgwithdrawvalidatorrewardsall) + - [MsgSetWithdrawAddress](04_messages.md#msgsetwithdrawaddress) + - [MsgWithdrawDelegatorReward](04_messages.md#msgwithdrawdelegatorreward) + - [Withdraw Validator Rewards All](04_messages.md#withdraw-validator-rewards-all) - [Common calculations ](04_messages.md#common-calculations-) 5. **[Hooks](05_hooks.md)** - [Create or modify delegation distribution](05_hooks.md#create-or-modify-delegation-distribution) From a64bd8cd9036b6ddae8419bd04b6d104844e34cf Mon Sep 17 00:00:00 2001 From: MD Aleem <72057206+aleem1314@users.noreply.github.com> Date: Mon, 11 Jan 2021 18:21:42 +0530 Subject: [PATCH 026/152] [docs] x/crisis - general audit and cleanup (#8269) * update docs * review changes Co-authored-by: atheeshp <59333759+atheeshp@users.noreply.github.com> --- x/crisis/spec/01_state.md | 2 +- x/crisis/spec/02_messages.md | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/x/crisis/spec/01_state.md b/x/crisis/spec/01_state.md index cbb949b0e327..581c79dc0e6d 100644 --- a/x/crisis/spec/01_state.md +++ b/x/crisis/spec/01_state.md @@ -14,5 +14,5 @@ with the standard gas consumption method. The ConstantFee param is held in the global params store. - - Params: `mint/params -> amino(sdk.Coin)` + - Params: `mint/params -> legacy_amino(sdk.Coin)` diff --git a/x/crisis/spec/02_messages.md b/x/crisis/spec/02_messages.md index 93a01aec2677..8634c8f9f506 100644 --- a/x/crisis/spec/02_messages.md +++ b/x/crisis/spec/02_messages.md @@ -11,12 +11,7 @@ corresponding updates to the state. Blockchain invariants can be checked using the `MsgVerifyInvariant` message. -```go -type MsgVerifyInvariant struct { - Sender sdk.AccAddress - InvariantRoute string -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc7/proto/cosmos/crisis/v1beta1/tx.proto#L14-L22 This message is expected to fail if: - the sender does not have enough coins for the constant fee From 4fa9e98095a6d5fc6a045adfe225f498854206bb Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 11 Jan 2021 21:08:56 +0000 Subject: [PATCH 027/152] fix reproducible builds (#8300) --- build.sh => .build.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename build.sh => .build.sh (100%) diff --git a/build.sh b/.build.sh similarity index 100% rename from build.sh rename to .build.sh From 9d67526dd798567dea775e9c78a7ff095783ccb9 Mon Sep 17 00:00:00 2001 From: SaReN Date: Tue, 12 Jan 2021 13:17:47 +0530 Subject: [PATCH 028/152] Fix sequence value in auth sign signature only (#8287) * fix signature only * add test, changelog * update test * Update CHANGELOG.md * address suggestions Co-authored-by: Alessio Treglia Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- CHANGELOG.md | 4 ++++ x/auth/client/cli/cli_test.go | 26 +++++++++++++++----------- x/auth/client/testutil/helpers.go | 28 +++++++++++----------------- x/auth/tx/sigs.go | 1 + 4 files changed, 31 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe247044e3c3..71c88b545407 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### Bug Fixes + + * (x/auth) [\#8287](https://github.com/cosmos/cosmos-sdk/pull/8287) Fix `tx sign --signature-only` to return correct sequence value in signature. + ## [v0.40.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0) - 2021-01-08 v0.40.0, known as the Stargate release of the Cosmos SDK, is one of the largest releases diff --git a/x/auth/client/cli/cli_test.go b/x/auth/client/cli/cli_test.go index 6a6a9b1d559e..fdd558b7971f 100644 --- a/x/auth/client/cli/cli_test.go +++ b/x/auth/client/cli/cli_test.go @@ -15,7 +15,6 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" @@ -145,11 +144,21 @@ func (s *IntegrationTestSuite) TestCLISign() { valInfo, err := val1.ClientCtx.Keyring.Key(val1.Moniker) require.NoError(err) + // query account info + queryResJSON, err := authtest.QueryAccountExec(val1.ClientCtx, val1.Address) + require.NoError(err) + var account authtypes.AccountI + require.NoError(val1.ClientCtx.JSONMarshaler.UnmarshalInterfaceJSON(queryResJSON.Bytes(), &account)) + /**** test signature-only ****/ res, err := authtest.TxSignExec(val1.ClientCtx, val1.Address, fileUnsigned.Name(), chainFlag, sigOnlyFlag) require.NoError(err) checkSignatures(require, txCfg, res.Bytes(), valInfo.GetPubKey()) + sigs, err := txCfg.UnmarshalSignatureJSON(res.Bytes()) + require.NoError(err) + require.Equal(1, len(sigs)) + require.Equal(account.GetSequence(), sigs[0].Sequence) /**** test full output ****/ res, err = authtest.TxSignExec(val1.ClientCtx, val1.Address, fileUnsigned.Name(), chainFlag) @@ -814,19 +823,17 @@ func (s *IntegrationTestSuite) TestGetAccountCmd() { testCases := []struct { name string - args []string + address sdk.AccAddress expectErr bool }{ { "invalid address", - []string{addr1.String(), - fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + addr1, true, }, { "valid address", - []string{val.Address.String(), - fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + val.Address, false, }, } @@ -834,18 +841,15 @@ func (s *IntegrationTestSuite) TestGetAccountCmd() { for _, tc := range testCases { tc := tc s.Run(tc.name, func() { - cmd := authcli.GetAccountCmd() clientCtx := val.ClientCtx - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + out, err := authtest.QueryAccountExec(clientCtx, tc.address) if tc.expectErr { s.Require().Error(err) s.Require().NotEqual("internal", err.Error()) } else { - var any types.Any - s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &any)) var acc authtypes.AccountI - s.Require().NoError(val.ClientCtx.InterfaceRegistry.UnpackAny(&any, &acc)) + s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalInterfaceJSON(out.Bytes(), &acc)) s.Require().Equal(val.Address, acc.GetAddress()) } }) diff --git a/x/auth/client/testutil/helpers.go b/x/auth/client/testutil/helpers.go index b46079cc6d95..e4f31727768e 100644 --- a/x/auth/client/testutil/helpers.go +++ b/x/auth/client/testutil/helpers.go @@ -23,12 +23,10 @@ func TxSignExec(clientCtx client.Context, from fmt.Stringer, filename string, ex filename, } - args = append(args, extraArgs...) - cmd := cli.GetSignCommand() tmcli.PrepareBaseCmd(cmd, "", "") - return clitestutil.ExecTestCLICmd(clientCtx, cmd, args) + return clitestutil.ExecTestCLICmd(clientCtx, cmd, append(args, extraArgs...)) } func TxBroadcastExec(clientCtx client.Context, filename string, extraArgs ...string) (testutil.BufferWriter, error) { @@ -36,9 +34,7 @@ func TxBroadcastExec(clientCtx client.Context, filename string, extraArgs ...str filename, } - args = append(args, extraArgs...) - - return clitestutil.ExecTestCLICmd(clientCtx, cli.GetBroadcastCommand(), args) + return clitestutil.ExecTestCLICmd(clientCtx, cli.GetBroadcastCommand(), append(args, extraArgs...)) } func TxEncodeExec(clientCtx client.Context, filename string, extraArgs ...string) (testutil.BufferWriter, error) { @@ -47,9 +43,7 @@ func TxEncodeExec(clientCtx client.Context, filename string, extraArgs ...string filename, } - args = append(args, extraArgs...) - - return clitestutil.ExecTestCLICmd(clientCtx, cli.GetEncodeCommand(), args) + return clitestutil.ExecTestCLICmd(clientCtx, cli.GetEncodeCommand(), append(args, extraArgs...)) } func TxValidateSignaturesExec(clientCtx client.Context, filename string) (testutil.BufferWriter, error) { @@ -70,9 +64,7 @@ func TxMultiSignExec(clientCtx client.Context, from string, filename string, ext from, } - args = append(args, extraArgs...) - - return clitestutil.ExecTestCLICmd(clientCtx, cli.GetMultiSignCommand(), args) + return clitestutil.ExecTestCLICmd(clientCtx, cli.GetMultiSignCommand(), append(args, extraArgs...)) } func TxSignBatchExec(clientCtx client.Context, from fmt.Stringer, filename string, extraArgs ...string) (testutil.BufferWriter, error) { @@ -82,9 +74,7 @@ func TxSignBatchExec(clientCtx client.Context, from fmt.Stringer, filename strin filename, } - args = append(args, extraArgs...) - - return clitestutil.ExecTestCLICmd(clientCtx, cli.GetSignBatchCommand(), args) + return clitestutil.ExecTestCLICmd(clientCtx, cli.GetSignBatchCommand(), append(args, extraArgs...)) } func TxDecodeExec(clientCtx client.Context, encodedTx string, extraArgs ...string) (testutil.BufferWriter, error) { @@ -93,9 +83,13 @@ func TxDecodeExec(clientCtx client.Context, encodedTx string, extraArgs ...strin encodedTx, } - args = append(args, extraArgs...) + return clitestutil.ExecTestCLICmd(clientCtx, cli.GetDecodeCommand(), append(args, extraArgs...)) +} + +func QueryAccountExec(clientCtx client.Context, address fmt.Stringer, extraArgs ...string) (testutil.BufferWriter, error) { + args := []string{address.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag)} - return clitestutil.ExecTestCLICmd(clientCtx, cli.GetDecodeCommand(), args) + return clitestutil.ExecTestCLICmd(clientCtx, cli.GetAccountCmd(), append(args, extraArgs...)) } // DONTCOVER diff --git a/x/auth/tx/sigs.go b/x/auth/tx/sigs.go index 5916a42c3342..e2d5d63a6015 100644 --- a/x/auth/tx/sigs.go +++ b/x/auth/tx/sigs.go @@ -118,6 +118,7 @@ func (g config) MarshalSignatureJSON(sigs []signing.SignatureV2) ([]byte, error) descs[i] = &signing.SignatureDescriptor{ PublicKey: any, Data: descData, + Sequence: sig.Sequence, } } From 40ce5a3e559c5b2f4bae0d94bff892cff8cf3689 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 12 Jan 2021 10:08:42 +0000 Subject: [PATCH 029/152] fix library file path (#8301) Co-authored-by: SaReN --- .build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.build.sh b/.build.sh index e48187f1cb93..1f7a1488371b 100755 --- a/.build.sh +++ b/.build.sh @@ -11,7 +11,7 @@ set -ue # - DEBUG # Source builder's functions library -. /usr/local/share/cosmos-sdk/buildlib.sh +. /usr/local/share/tendermint/buildlib.sh # These variables are now available # - BASEDIR From 046b1a4da589e03221003ba595dc383e6681142e Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Tue, 12 Jan 2021 16:54:27 -0300 Subject: [PATCH 030/152] deps: bump tendermint to v0.34.2 (#8316) * deps: bump tendermint to v0.34.2 * changelog * tidy --- CHANGELOG.md | 4 ++++ go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71c88b545407..aa8f7658ec25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### Improvements + +* (tendermint) [\#8316](https://github.com/cosmos/cosmos-sdk/pull/8316) Bump Tendermint version to [v0.34.2](https://github.com/tendermint/tendermint/releases/tag/v0.34.2) + ### Bug Fixes * (x/auth) [\#8287](https://github.com/cosmos/cosmos-sdk/pull/8287) Fix `tx sign --signature-only` to return correct sequence value in signature. diff --git a/go.mod b/go.mod index 185962ff44a6..d7b0e4c2f0af 100644 --- a/go.mod +++ b/go.mod @@ -46,7 +46,7 @@ require ( github.com/tendermint/btcd v0.1.1 github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 github.com/tendermint/go-amino v0.16.0 - github.com/tendermint/tendermint v0.34.1 + github.com/tendermint/tendermint v0.34.2 github.com/tendermint/tm-db v0.6.3 golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad golang.org/x/net v0.0.0-20200930145003-4acb6c075d10 // indirect diff --git a/go.sum b/go.sum index b9231e178ea5..c6f3183a55e4 100644 --- a/go.sum +++ b/go.sum @@ -562,8 +562,8 @@ github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxm github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg= github.com/tendermint/tendermint v0.34.0 h1:eXCfMgoqVSzrjzOj6clI9GAejcHH0LvOlRjpCmMJksU= github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= -github.com/tendermint/tendermint v0.34.1 h1:TsJXY8+1NThc/XIENMv1ENzazriHBJJjeP6hN3kpC8g= -github.com/tendermint/tendermint v0.34.1/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= +github.com/tendermint/tendermint v0.34.2 h1:bB4xReGw4jalTDeNg0npYoONuZrD55F90LrWPF4m/PQ= +github.com/tendermint/tendermint v0.34.2/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI= github.com/tendermint/tm-db v0.6.3 h1:ZkhQcKnB8/2jr5EaZwGndN4owkPsGezW2fSisS9zGbg= github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8= From ef35ba69f9cc791b78c74380e191d2d7a2018186 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Wed, 13 Jan 2021 10:52:54 +0100 Subject: [PATCH 031/152] add cosmovisot to running a node (#8320) --- docs/run-node/README.md | 1 + docs/{using-the-sdk => run-node}/cosmovisor.md | 0 docs/using-the-sdk/README.md | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) rename docs/{using-the-sdk => run-node}/cosmovisor.md (100%) diff --git a/docs/run-node/README.md b/docs/run-node/README.md index 2ae01b8541e4..0a2f24b87939 100644 --- a/docs/run-node/README.md +++ b/docs/run-node/README.md @@ -12,3 +12,4 @@ This folder contains documentation on how to run a node and interact with it. 1. [Running a Node](./run-node.md) 1. [Interacting with a Node](./interact-node.md) 1. [Generating, Signing and Broadcasting Transactions](./txs.md) +1. [Cosmos Upgrade Manager](./cosmovisor.md) diff --git a/docs/using-the-sdk/cosmovisor.md b/docs/run-node/cosmovisor.md similarity index 100% rename from docs/using-the-sdk/cosmovisor.md rename to docs/run-node/cosmovisor.md diff --git a/docs/using-the-sdk/README.md b/docs/using-the-sdk/README.md index fb645c679cc4..747dfd500553 100644 --- a/docs/using-the-sdk/README.md +++ b/docs/using-the-sdk/README.md @@ -7,4 +7,3 @@ parent: - [Modules](../../x/README.md) - [Simulation](./simulation.md) -- [Cosmos Upgrade Manager](./cosmovisor.md) From b4bc63dd78473f1503a5f05fedb72f6ba6cea61b Mon Sep 17 00:00:00 2001 From: Tobias Schwarz Date: Wed, 13 Jan 2021 11:01:02 +0100 Subject: [PATCH 032/152] Chain Upgrade Guide: new_v040_genesis.json (#8313) Genesis name changes from `new_v040_genesis.json` to `new_040_genesis.json` in this command. This is probably a typo Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/migrations/chain-upgrade-guide-040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/migrations/chain-upgrade-guide-040.md b/docs/migrations/chain-upgrade-guide-040.md index ca8f0b94d514..abb9f975bddf 100644 --- a/docs/migrations/chain-upgrade-guide-040.md +++ b/docs/migrations/chain-upgrade-guide-040.md @@ -87,7 +87,7 @@ software and restore to their latest snapshot before restarting their nodes. 1) If your chain is using IBC, make sure to add IBC initial genesis state to the genesis file. You can use the following command to add IBC initial genesis state to the genesis file. ```shell - cat new_040_genesis.json | jq '.app_state |= . + {"ibc":{"client_genesis":{"clients":[],"clients_consensus":[],"create_localhost":false},"connection_genesis":{"connections":[],"client_connection_paths":[]},"channel_genesis":{"channels":[],"acknowledgements":[],"commitments":[],"receipts":[],"send_sequences":[],"recv_sequences":[],"ack_sequences":[]}},"transfer":{"port_id":"transfer","denom_traces":[],"params":{"send_enabled":false,"receive_enabled":false}},"capability":{"index":"1","owners":[]}}' > new_040_genesis.json + cat new_v040_genesis.json | jq '.app_state |= . + {"ibc":{"client_genesis":{"clients":[],"clients_consensus":[],"create_localhost":false},"connection_genesis":{"connections":[],"client_connection_paths":[]},"channel_genesis":{"channels":[],"acknowledgements":[],"commitments":[],"receipts":[],"send_sequences":[],"recv_sequences":[],"ack_sequences":[]}},"transfer":{"port_id":"transfer","denom_traces":[],"params":{"send_enabled":false,"receive_enabled":false}},"capability":{"index":"1","owners":[]}}' > new_v040_genesis.json ``` **Note:** This would add IBC state with IBC's `send_enabled: false` and `receive_enabled: false`. Make sure to update them to `true` in the above command if are planning to enable IBC transactions with chain upgrade. Otherwise you can do it via a governance proposal. From eafd1bc945dfcb84e809811eca5e71ea350f0946 Mon Sep 17 00:00:00 2001 From: atheeshp <59333759+atheeshp@users.noreply.github.com> Date: Wed, 13 Jan 2021 17:25:51 +0530 Subject: [PATCH 033/152] x/gov docs basic cleanup (#8279) * update docs * review changes * review changes * review changes * review changes * review changes Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- x/gov/spec/01_concepts.md | 16 +++++++++---- x/gov/spec/02_state.md | 48 +++++++-------------------------------- x/gov/spec/03_messages.md | 42 +++++++++++----------------------- 3 files changed, 32 insertions(+), 74 deletions(-) diff --git a/x/gov/spec/01_concepts.md b/x/gov/spec/01_concepts.md index 0acbfa3b709b..becb7cc6de2f 100644 --- a/x/gov/spec/01_concepts.md +++ b/x/gov/spec/01_concepts.md @@ -29,18 +29,24 @@ its unique `proposalID`. ### Proposal types -In the initial version of the governance module, there are two types of -proposal: +In the initial version of the governance module, there are five types of +proposals: -- `PlainTextProposal` All the proposals that do not involve a modification of +- `TextProposal` All the proposals that do not involve a modification of the source code go under this type. For example, an opinion poll would use a - proposal of type `PlainTextProposal`. + proposal of type `TextProposal`. - `SoftwareUpgradeProposal`. If accepted, validators are expected to update their software in accordance with the proposal. They must do so by following a 2-steps process described in the [Software Upgrade](#software-upgrade) section below. Software upgrade roadmap may be discussed and agreed on via - `PlainTextProposals`, but actual software upgrades must be performed via + `TextProposals`, but actual software upgrades must be performed via `SoftwareUpgradeProposals`. +- `CommunityPoolSpendProposal` details a proposal for use of community funds, + together with how many coins are proposed to be spent, and to which recipient account. +- `ParameterChangeProposal` defines a proposal to change one or + more parameters. If accepted, the requested parameter change is updated + automatically by the proposal handler upon conclusion of the voting period. +- `CancelSoftwareUpgradeProposal` is a gov Content type for cancelling a software upgrade. Other modules may expand upon the governance module by implementing their own proposal types and handlers. These types are registered and processed through the diff --git a/x/gov/spec/02_state.md b/x/gov/spec/02_state.md index ba3b12b3f3a7..4175367fdfb8 100644 --- a/x/gov/spec/02_state.md +++ b/x/gov/spec/02_state.md @@ -11,26 +11,14 @@ be one active parameter set at any given time. If governance wants to change a parameter set, either to modify a value or add/remove a parameter field, a new parameter set has to be created and the previous one rendered inactive. -```go -type DepositParams struct { - MinDeposit sdk.Coins // Minimum deposit for a proposal to enter voting period. - MaxDepositPeriod time.Time // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months -} -``` +### DepositParams ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/gov.proto#L127-L145 -```go -type VotingParams struct { - VotingPeriod time.Time // Length of the voting period. Initial value: 2 weeks -} -``` +### VotingParams ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/gov.proto#L147-L156 -```go -type TallyParams struct { - Quorum sdk.Dec // Minimum percentage of stake that needs to vote for a proposal to be considered valid - Threshold sdk.Dec // Minimum proportion of Yes votes for proposal to pass. Initial value: 0.5 - Veto sdk.Dec // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3 -} -``` +### TallyParams ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/gov.proto#L158-L183 Parameters are stored in a global `GlobalParams` KVStore. @@ -68,12 +56,7 @@ const ( ## Deposit -```go - type Deposit struct { - Amount sdk.Coins // Amount of coins deposited by depositor - Depositor crypto.address // Address of depositor - } -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/gov.proto#L43-L53 ## ValidatorGovInfo @@ -92,22 +75,7 @@ This type is used in a temp map when tallying what this proposal is about, and other fields, which are the mutable state of the governance process. -```go -type Proposal struct { - Content // Proposal content interface - - ProposalID uint64 - Status ProposalStatus // Status of the Proposal {Pending, Active, Passed, Rejected} - FinalTallyResult TallyResult // Result of Tallies - - SubmitTime time.Time // Time of the block where TxGovSubmitProposal was included - DepositEndTime time.Time // Time that the Proposal would expire if deposit amount isn't met - TotalDeposit sdk.Coins // Current deposit on this proposal. Initial value is set at InitialDeposit - - VotingStartTime time.Time // Time of the block where MinDeposit was reached. -1 if MinDeposit is not reached - VotingEndTime time.Time // Time that the VotingPeriod for this proposal will end and votes will be tallied -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/gov.proto#L55-L77 ```go type Content interface { diff --git a/x/gov/spec/03_messages.md b/x/gov/spec/03_messages.md index cac55b5ed945..59aa255f4cb4 100644 --- a/x/gov/spec/03_messages.md +++ b/x/gov/spec/03_messages.md @@ -6,18 +6,12 @@ order: 3 ## Proposal Submission -Proposals can be submitted by any Atom holder via a `TxGovSubmitProposal` +Proposals can be submitted by any account via a `MsgSubmitProposal` transaction. -```go -type TxGovSubmitProposal struct { - Content Content - InitialDeposit sdk.Coins - Proposer sdk.AccAddress -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/tx.proto#L24-L39 -The `Content` of a `TxGovSubmitProposal` message must have an appropriate router +The `Content` of a `MsgSubmitProposal` message must have an appropriate router set in the governance module. **State modifications:** @@ -30,12 +24,12 @@ set in the governance module. - Push `proposalID` in `ProposalProcessingQueue` - Transfer `InitialDeposit` from the `Proposer` to the governance `ModuleAccount` -A `TxGovSubmitProposal` transaction can be handled according to the following +A `MsgSubmitProposal` transaction can be handled according to the following pseudocode. ```go // PSEUDOCODE // -// Check if TxGovSubmitProposal is valid. If it is, create proposal // +// Check if MsgSubmitProposal is valid. If it is, create proposal // upon receiving txGovSubmitProposal from sender do @@ -79,14 +73,9 @@ upon receiving txGovSubmitProposal from sender do Once a proposal is submitted, if `Proposal.TotalDeposit < ActiveParam.MinDeposit`, Atom holders can send -`TxGovDeposit` transactions to increase the proposal's deposit. +`MsgDeposit` transactions to increase the proposal's deposit. -```go -type TxGovDeposit struct { - ProposalID int64 // ID of the proposal - Deposit sdk.Coins // Number of Atoms to add to the proposal's deposit -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/tx.proto#L61-L72 **State modifications:** @@ -97,12 +86,12 @@ type TxGovDeposit struct { - Push `proposalID` in `ProposalProcessingQueueEnd` - Transfer `Deposit` from the `proposer` to the governance `ModuleAccount` -A `TxGovDeposit` transaction has to go through a number of checks to be valid. +A `MsgDeposit` transaction has to go through a number of checks to be valid. These checks are outlined in the following pseudocode. ```go // PSEUDOCODE // -// Check if TxGovDeposit is valid. If it is, increase deposit and check if MinDeposit is reached +// Check if MsgDeposit is valid. If it is, increase deposit and check if MinDeposit is reached upon receiving txGovDeposit from sender do // check if proposal is correctly formatted. Includes fee payment. @@ -149,15 +138,10 @@ upon receiving txGovDeposit from sender do ## Vote Once `ActiveParam.MinDeposit` is reached, voting period starts. From there, -bonded Atom holders are able to send `TxGovVote` transactions to cast their +bonded Atom holders are able to send `MsgVote` transactions to cast their vote on the proposal. -```go - type TxGovVote struct { - ProposalID int64 // proposalID of the proposal - Vote byte // option from OptionSet chosen by the voter - } -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/tx.proto#L46-L56 **State modifications:** @@ -165,12 +149,12 @@ vote on the proposal. _Note: Gas cost for this message has to take into account the future tallying of the vote in EndBlocker_ -Next is a pseudocode proposal of the way `TxGovVote` transactions are +Next is a pseudocode outline of the way `MsgVote` transactions are handled: ```go // PSEUDOCODE // - // Check if TxGovVote is valid. If it is, count vote// + // Check if MsgVote is valid. If it is, count vote// upon receiving txGovVote from sender do // check if proposal is correctly formatted. Includes fee payment. From df7f0b2741015440e599d6aefe92e2423b69b643 Mon Sep 17 00:00:00 2001 From: Marko Date: Wed, 13 Jan 2021 18:41:50 +0100 Subject: [PATCH 034/152] docs: deploy to github pages (#8321) --- .circleci/config.yml | 64 -------------------------------------- .github/workflows/docs.yml | 31 ++++++++++++++++++ Makefile | 9 +----- 3 files changed, 32 insertions(+), 72 deletions(-) delete mode 100644 .circleci/config.yml create mode 100644 .github/workflows/docs.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 099db02d8a33..000000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,64 +0,0 @@ -version: 2.1 - -executors: - docs: - docker: - - image: tendermintdev/docker-website-deployment - environment: - AWS_REGION: us-east-1 - -commands: - make: - parameters: - description: - type: string - target: - type: string - steps: - - attach_workspace: - at: /tmp/workspace - - restore_cache: - name: "Restore source code cache" - keys: - - go-src-v1-{{ .Revision }} - - checkout - - restore_cache: - name: "Restore go modules cache" - keys: - - go-mod-v2-{{ checksum "go.sum" }} - - run: - name: << parameters.description >> - command: | - make << parameters.target >> - -jobs: - build-docs: - executor: docs - steps: - - checkout - - run: - name: "Build docs" - command: make build-docs LEDGER_ENABLED=false - - run: - name: "Upload docs to S3" - command: make sync-docs LEDGER_ENABLED=false - -workflows: - version: 2 - test-suite: - jobs: - - build-docs: - context: docs-deployment-master - filters: - branches: - only: - - docs-staging - - build-docs: - context: docs-deployment-release - filters: - branches: - only: - - master - tags: - only: - - /v.*/ diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 000000000000..9c8fc8fbae0c --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,31 @@ +name: Documentation +# This job builds and deploys documenation to github pages. +# It runs on every push to master. +on: + push: + branches: + - master + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + container: + image: tendermintdev/docker-website-deployment + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v2.3.1 + with: + persist-credentials: false + fetch-depth: 0 + + - name: Install and Build 🔧 + run: | + apk add rsync + make build-docs LEDGER_ENABLED=false + + - name: Deploy 🚀 + uses: JamesIves/github-pages-deploy-action@3.7.1 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BRANCH: gh-pages + FOLDER: ~/output diff --git a/Makefile b/Makefile index d72d69f20d2d..6f498b36b3c6 100644 --- a/Makefile +++ b/Makefile @@ -201,14 +201,7 @@ build-docs: cp -r .vuepress/dist/* ~/output/$${path_prefix}/ ; \ cp ~/output/$${path_prefix}/index.html ~/output ; \ done < versions ; - -sync-docs: - cd ~/output && \ - echo "role_arn = ${DEPLOYMENT_ROLE_ARN}" >> /root/.aws/config ; \ - echo "CI job = ${CIRCLE_BUILD_URL}" >> version.html ; \ - aws s3 sync . s3://${WEBSITE_BUCKET} --profile terraform --delete ; \ - aws cloudfront create-invalidation --distribution-id ${CF_DISTRIBUTION_ID} --profile terraform --path "/*" ; -.PHONY: sync-docs +.PHONY: build-docs ############################################################################### ### Tests & Simulation ### From 2a2c2ec009c6087f4536ec01e497b256523969a1 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Wed, 13 Jan 2021 14:18:19 -0500 Subject: [PATCH 035/152] ADR 030: Authorization Module (#7105) * Add ADR 030 * Cleanup * Updates * Updates based on ADR 031 * Add abstract and context * Updates * Update module name as per #7615 * Updates from reviews * Rename * CLI update * Update docs/architecture/adr-030-authz-module.md Co-authored-by: Robert Zaremba * Update docs/architecture/adr-030-authz-module.md Co-authored-by: Robert Zaremba * Update docs/architecture/adr-030-authz-module.md Co-authored-by: Robert Zaremba * Update docs/architecture/adr-030-authz-module.md Co-authored-by: Robert Zaremba * Code review updates * Update docs Co-authored-by: Alessio Treglia Co-authored-by: Robert Zaremba --- docs/architecture/README.md | 1 + docs/architecture/adr-030-authz-module.md | 230 ++++++++++++++++++++++ 2 files changed, 231 insertions(+) create mode 100644 docs/architecture/adr-030-authz-module.md diff --git a/docs/architecture/README.md b/docs/architecture/README.md index 54cc9c89e4f7..a979f30e418c 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -53,6 +53,7 @@ Read about the [PROCESS](./PROCESS.md). - [ADR 023: Protocol Buffer Naming and Versioning](./adr-023-protobuf-naming.md) - [ADR 026: IBC Client Recovery Mechanisms](./adr-026-ibc-client-recovery-mechanisms.md) - [ADR 029: Fee Grant Module](./adr-029-fee-grant-module.md) +- [ADR 030: Message Authorization Module](architecture/adr-030-authz-module.md) - [ADR 031: Protobuf Msg Services](./adr-031-msg-service.md) ### Proposed diff --git a/docs/architecture/adr-030-authz-module.md b/docs/architecture/adr-030-authz-module.md new file mode 100644 index 000000000000..c61940fce8ea --- /dev/null +++ b/docs/architecture/adr-030-authz-module.md @@ -0,0 +1,230 @@ +# ADR 030: Authorization Module + +## Changelog + +- 2019-11-06: Initial Draft +- 2020-10-12: Updated Draft +- 2021-11-13: Accepted + +## Status + +Accepted + +## Abstract + +This ADR defines the `x/authz` module which allows accounts to grant authorizations to perform actions +on behalf of that account to other accounts. + +## Context + +The concrete use cases which motivated this module include: +- the desire to delegate the ability to vote on proposals to other accounts besides the account which one has +delegated stake +- "sub-keys" functionality, as originally proposed in [\#4480](https://github.com/cosmos/cosmos-sdk/issues/4480) which +is a term used to describe the functionality provided by this module together with +the `fee_grant` module from [ADR 029](./adr-029-fee-grant-module.md) and the [group module](https://github.com/regen-network/cosmos-modules/tree/master/incubator/group). + +The "sub-keys" functionality roughly refers to the ability for one account to grant some subset of its capabilities to +other accounts with possibly less robust, but easier to use security measures. For instance, a master account representing +an organization could grant the ability to spend small amounts of the organization's funds to individual employee accounts. +Or an individual (or group) with a multisig wallet could grant the ability to vote on proposals to any one of the member +keys. + +The current +implementation is based on work done by the [Gaian's team at Hackatom Berlin 2019](https://github.com/cosmos-gaians/cosmos-sdk/tree/hackatom/x/delegation). + +## Decision + +We will create a module named `authz` which provides functionality for +granting arbitrary privileges from one account (the _granter_) to another account (the _grantee_). Authorizations +must be granted for a particular `Msg` service methods one by one using an implementation +of `Authorization`. + +### Types + +Authorizations determine exactly what privileges are granted. They are extensible +and can be defined for any `Msg` service method even outside of the module where +the `Msg` method is defined. `Authorization`s use the new `ServiceMsg` type from +ADR 031. + +#### Authorization + +```go +type Authorization interface { + // MethodName returns the fully-qualified Msg service method name as described in ADR 031. + MethodName() string + + // Accept determines whether this grant permits the provided sdk.ServiceMsg to be performed, and if + // so provides an upgraded authorization instance. + // Returns: + // + allow: true if msg is authorized + // + updated: new Authorization instance which should overwrite the current one with new state + // + delete: true if Authorization has been exhausted and can be deleted from state + Accept(msg sdk.ServiceMsg, block abci.Header) (allow bool, updated Authorization, delete bool) +} +``` + +For example a `SendAuthorization` like this is defined for `MsgSend` that takes +a `SpendLimit` and updates it down to zero: + +```go +type SendAuthorization struct { + // SpendLimit specifies the maximum amount of tokens that can be spent + // by this authorization and will be updated as tokens are spent. If it is + // empty, there is no spend limit and any amount of coins can be spent. + SpendLimit sdk.Coins +} + +func (cap SendAuthorization) MethodName() string { + return "/cosmos.bank.v1beta1.Msg/Send" +} + +func (cap SendAuthorization) Accept(msg sdk.ServiceMsg, block abci.Header) (allow bool, updated Authorization, delete bool) { + switch req := msg.Request.(type) { + case bank.MsgSend: + left, invalid := cap.SpendLimit.SafeSub(req.Amount) + if invalid { + return false, nil, false + } + if left.IsZero() { + return true, nil, true + } + return true, SendAuthorization{SpendLimit: left}, false + } + return false, nil, false +} +``` + +A different type of capability for `MsgSend` could be implemented +using the `Authorization` interface with no need to change the underlying +`bank` module. + +### `Msg` Service + +```proto +service Msg { + // GrantAuthorization grants the provided authorization to the grantee on the granter's + // account with the provided expiration time. + rpc GrantAuthorization(MsgGrantAuthorization) returns (MsgGrantAuthorizationResponse); + + // ExecAuthorized attempts to execute the provided messages using + // authorizations granted to the grantee. Each message should have only + // one signer corresponding to the granter of the authorization. + // The grantee signing this message must have an authorization from the granter. + rpc ExecAuthorized(MsgExecAuthorized) returns (MsgExecAuthorizedResponse) + + + // RevokeAuthorization revokes any authorization corresponding to the provided method name on the + // granter's account that has been granted to the grantee. + rpc RevokeAuthorization(MsgRevokeAuthorization) returns (MsgRevokeAuthorizationResponse); +} + +message MsgGrantAuthorization{ + string granter = 1; + string grantee = 2; + google.protobuf.Any authorization = 3 [(cosmos_proto.accepts_interface) = "Authorization"]; + google.protobuf.Timestamp expiration = 4; +} + +message MsgExecAuthorized { + string grantee = 1; + repeated google.protobuf.Any msgs = 2; +} + +message MsgRevokeAuthorization{ + string granter = 1; + string grantee = 2; + string method_name = 3; +} +``` + +### Router Middleware + +The `authz` `Keeper` will expose a `DispatchActions` method which allows other modules to send `ServiceMsg`s +to the router based on `Authorization` grants: + +```go +type Keeper interface { + // DispatchActions routes the provided msgs to their respective handlers if the grantee was granted an authorization + // to send those messages by the first (and only) signer of each msg. + DispatchActions(ctx sdk.Context, grantee sdk.AccAddress, msgs []sdk.ServiceMsg) sdk.Result` +} +``` + +This allows the functionality provided by `authz` to be used for future inter-module object capabilities +permissions as described in [ADR 033](https://github.com/cosmos/cosmos-sdk/7459) + +### CLI + +#### `tx exec` Method + +When a CLI user wants to run a transaction on behalf of another account using `MsgExecAuthorized`, they +can use the `exec` method. For instance `gaiacli tx gov vote 1 yes --from --generate-only | gaiacli tx authz exec --send-as --from ` +would send a transaction like this: + +```go +MsgExecAuthorized { + Grantee: mykey, + Msgs: []sdk.SericeMsg{ + ServiceMsg { + MethodName:"/cosmos.gov.v1beta1.Msg/Vote" + Request: MsgVote { + ProposalID: 1, + Voter: cosmos3thsdgh983egh823 + Option: Yes + } + } + } +} +``` + +#### `tx grant --from ` + +This CLI command will send a `MsgGrantAuthorization` transaction. `authorization` should be encoded as +JSON on the CLI. + +#### `tx revoke --from ` + +This CLI command will send a `MsgRevokeAuthorization` transaction. + +### Built-in Authorizations + +#### `SendAuthorization` + +```proto +// SendAuthorization allows the grantee to spend up to spend_limit coins from +// the granter's account. +message SendAuthorization { + repeated cosmos.base.v1beta1.Coin spend_limit = 1; +} +``` + +#### `GenericAuthorization` + +```proto +// GenericAuthorization gives the grantee unrestricted permissions to execute +// the provide method on behalf of the granter's account. +message GenericAuthorization { + string method_name = 1; +} +``` + +## Consequences + +### Positive + +- Users will be able to authorize arbitrary actions on behalf of their accounts to other +users, improving key management for many use cases +- The solution is more generic than previously considered approaches and the +`Authorization` interface approach can be extended to cover other use cases by +SDK users + +### Negative + +### Neutral + +## References + +- Initial Hackatom implementation: https://github.com/cosmos-gaians/cosmos-sdk/tree/hackatom/x/delegation +- Post-Hackatom spec: https://gist.github.com/aaronc/b60628017352df5983791cad30babe56#delegation-module +- B-Harvest subkeys spec: https://github.com/cosmos/cosmos-sdk/issues/4480 From 334b2238d84191df89acea9073a621dda57ea9c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Jan 2021 08:41:03 -0300 Subject: [PATCH 036/152] build(deps): bump github.com/stretchr/testify from 1.6.1 to 1.7.0 (#8330) Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.6.1 to 1.7.0. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.6.1...v1.7.0) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index d7b0e4c2f0af..417471e79de5 100644 --- a/go.mod +++ b/go.mod @@ -42,7 +42,7 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect; indirects github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.7.1 - github.com/stretchr/testify v1.6.1 + github.com/stretchr/testify v1.7.0 github.com/tendermint/btcd v0.1.1 github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 github.com/tendermint/go-amino v0.16.0 diff --git a/go.sum b/go.sum index c6f3183a55e4..5d526fc85041 100644 --- a/go.sum +++ b/go.sum @@ -546,6 +546,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca h1:Ld/zXl5t4+D69SiV4JoN7kkfvJdOWlPpfxrzxpLMoUk= From 1b1dbf8ab722e4689e14a5a2a1fc433b69bc155e Mon Sep 17 00:00:00 2001 From: Marie Gauthier Date: Fri, 15 Jan 2021 14:30:17 +0100 Subject: [PATCH 037/152] x/params docs general audit & cleanup (#8295) * Update doc.go * Update spec/ * More updates * Update README Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- x/params/doc.go | 21 ++++++++++----------- x/params/spec/01_keeper.md | 18 +++++------------- x/params/spec/02_subspace.md | 16 +++++++--------- x/params/spec/README.md | 5 ++--- 4 files changed, 24 insertions(+), 36 deletions(-) diff --git a/x/params/doc.go b/x/params/doc.go index 68ab4dee0e1f..2a79b0fd51a6 100644 --- a/x/params/doc.go +++ b/x/params/doc.go @@ -6,9 +6,8 @@ namespace for a parameter store, where keys are prefixed by pre-configured subspace names which modules provide. The Keeper has a permission to access all existing subspaces. -Subspace can be used by the individual keepers, who needs a private parameter store -that the other keeper cannot modify. Keeper can be used by the Governance keeper, -who need to modify any parameter in case of the proposal passes. +Subspace can be used by the individual keepers, which need a private parameter store +that the other keepers cannot modify. Basic Usage: @@ -23,11 +22,11 @@ Basic Usage: KeyParameter2 = "myparameter2" ) -2. Create a concrete parameter struct and define the validation functions: +2. Define parameters as proto message and define the validation functions: - type MyParams struct { - MyParam1 int64 `json:"my_param1" yaml:"my_param1"` - MyParam2 bool `json:"my_param2" yaml:"my_param2"` + message MyParams { + int64 my_param1 = 1; + bool my_param2 = 2; } func validateMyParam1(i interface{}) error { @@ -56,12 +55,12 @@ Basic Usage: func (p *MyParams) ParamSetPairs() params.ParamSetPairs { return params.ParamSetPairs{ - {KeyParameter1, &p.MyParam1, validateMyParam1}, - {KeyParameter2, &p.MyParam2, validateMyParam2}, + params.NewParamSetPair(KeyParameter1, &p.MyParam1, validateMyParam1), + params.NewParamSetPair(KeyParameter2, &p.MyParam2, validateMyParam2), } } - func paramKeyTable() params.KeyTable { + func ParamKeyTable() params.KeyTable { return params.NewKeyTable().RegisterParamSet(&MyParams{}) } @@ -70,7 +69,7 @@ Basic Usage: func NewKeeper(..., paramSpace params.Subspace, ...) Keeper { // set KeyTable if it has not already been set if !paramSpace.HasKeyTable() { - paramSpace = paramSpace.WithKeyTable(paramKeyTable()) + paramSpace = paramSpace.WithKeyTable(ParamKeyTable()) } return Keeper { diff --git a/x/params/spec/01_keeper.md b/x/params/spec/01_keeper.md index 8cf7e2a53f97..fa97ec5b37fc 100644 --- a/x/params/spec/01_keeper.md +++ b/x/params/spec/01_keeper.md @@ -4,24 +4,16 @@ order: 1 # Keeper -In the app initialization stage, `Keeper.Subspace(Paramspace)` is passed to the -user modules, and the subspaces are stored in `Keeper.spaces`. Later it can be -retrieved with `Keeper.GetSubspace`, so the keepers holding `Keeper` can access -to any subspace. For example, Gov module can take `Keeper` as its argument and -modify parameter of any subspace when a `ParameterChangeProposal` is accepted. +In the app initialization stage, [subspaces](02_subspace.md) can be allocated for other modules' keeper using `Keeper.Subspace` and are stored in `Keeper.spaces`. Then, those modules can have a reference to their specific parameter store through `Keeper.GetSubspace`. Example: ```go -type MasterKeeper struct { - pk params.Keeper +type ExampleKeeper struct { + paramSpace paramtypes.Subspace } -func (k MasterKeeper) SetParam(ctx sdk.Context, space string, key string, param interface{}) { - space, ok := k.ps.GetSubspace(space) - if !ok { - return - } - space.Set(ctx, key, param) +func (k ExampleKeeper) SetParams(ctx sdk.Context, params types.Params) { + k.paramSpace.SetParamSet(ctx, ¶ms) } ``` diff --git a/x/params/spec/02_subspace.md b/x/params/spec/02_subspace.md index 5e36eaf498f5..e6ffa760d208 100644 --- a/x/params/spec/02_subspace.md +++ b/x/params/spec/02_subspace.md @@ -4,8 +4,8 @@ order: 2 # Subspace -`Subspace` is a prefixed subspace of the parameter store. Each module who use the -parameter store will take a `Subspace`, not the `Keeper`, to isolate permission to access. +`Subspace` is a prefixed subspace of the parameter store. Each module which uses the +parameter store will take a `Subspace` to isolate permission to access. ## Key @@ -21,20 +21,18 @@ Subkeys can be used for grouping or dynamic parameter key generation during runt All of the parameter keys that will be used should be registered at the compile time. `KeyTable` is essentially a `map[string]attribute`, where the `string` is a parameter key. -Currently, `attribute` only consists of `reflect.Type`, which indicates the parameter -type. It is needed even if the state machine has no error, because the paraeter -can be modified externally, for example via the governance. +Currently, `attribute` consists of a `reflect.Type`, which indicates the parameter +type to check that provided key and value are compatible and registered, as well as a function `ValueValidatorFn` to validate values. Only primary keys have to be registered on the `KeyTable`. Subkeys inherit the attribute of the primary key. ## ParamSet -Modules often define a struct of parameters. Instead of calling methods with -each of those parameters, when the struct implements `ParamSet`, it can be used -with the following methods: +Modules often define parameters as a proto message. The generated struct can implement +`ParamSet` interface to be used with the following methods: * `KeyTable.RegisterParamSet()`: registers all parameters in the struct * `Subspace.{Get, Set}ParamSet()`: Get to & Set from the struct -The implementor should be a pointer in order to use `GetParamSet()` +The implementor should be a pointer in order to use `GetParamSet()`. diff --git a/x/params/spec/README.md b/x/params/spec/README.md index c84ad6e5bc9a..4a136cce57e3 100644 --- a/x/params/spec/README.md +++ b/x/params/spec/README.md @@ -15,9 +15,8 @@ There are two main types, Keeper and Subspace. Subspace is an isolated namespace paramstore, where keys are prefixed by preconfigured spacename. Keeper has a permission to access all existing spaces. -Subspace can be used by the individual keepers, who needs a private parameter store -that the other keeper cannot modify. Keeper can be used by the Governance keeper, -who need to modify any parameter in case of the proposal passes. +Subspace can be used by the individual keepers, which need a private parameter store +that the other keepers cannot modify. The params Keeper can be used to add a route to `x/gov` router in order to modify any parameter in case a proposal passes. The following contents explains how to use params module for master and user modules. From 2521964d50735d719e398907c52639202c38e599 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Fri, 15 Jan 2021 14:45:34 -0500 Subject: [PATCH 038/152] Update gogo proto deps with v1.3.2 security fixes (#8350) * Update gogo proto deps with v1.3.2 security fixes * Regenerate proto files --- client/grpc/reflection/reflection.pb.go | 20 +- client/grpc/reflection/reflection.pb.gw.go | 88 -- client/grpc/tmservice/query.pb.go | 75 +- client/grpc/tmservice/query.pb.gw.go | 236 ----- crypto/keys/ed25519/keys.pb.go | 10 +- crypto/keys/multisig/keys.pb.go | 5 +- crypto/keys/secp256k1/keys.pb.go | 10 +- crypto/types/multisig.pb.go | 10 +- docs/core/proto-docs.md | 4 +- go.mod | 9 +- go.sum | 30 +- snapshots/types/snapshot.pb.go | 10 +- store/types/commit_info.pb.go | 15 +- store/types/snapshot.pb.go | 15 +- testutil/testdata/query.pb.go | 30 +- testutil/testdata/testdata.pb.go | 30 +- testutil/testdata/tx.pb.go | 15 +- testutil/testdata/unknonwnproto.pb.go | 162 +-- types/abci.pb.go | 50 +- types/coin.pb.go | 20 +- types/kv/kv.pb.go | 10 +- types/query/pagination.pb.go | 10 +- types/tx/service.pb.go | 40 +- types/tx/service.pb.gw.go | 169 ---- types/tx/signing/signing.pb.go | 25 +- types/tx/tx.pb.go | 50 +- x/auth/types/auth.pb.go | 15 +- x/auth/types/genesis.pb.go | 5 +- x/auth/types/query.pb.go | 20 +- x/auth/types/query.pb.gw.go | 88 -- x/auth/vesting/types/tx.pb.go | 10 +- x/auth/vesting/types/vesting.pb.go | 25 +- x/bank/types/bank.pb.go | 35 +- x/bank/types/genesis.pb.go | 10 +- x/bank/types/query.pb.go | 50 +- x/bank/types/query.pb.gw.go | 229 ----- x/bank/types/tx.pb.go | 20 +- x/capability/types/capability.pb.go | 15 +- x/capability/types/genesis.pb.go | 10 +- x/crisis/types/genesis.pb.go | 5 +- x/crisis/types/tx.pb.go | 10 +- x/distribution/types/distribution.pb.go | 60 +- x/distribution/types/genesis.pb.go | 40 +- x/distribution/types/query.pb.go | 90 +- x/distribution/types/query.pb.gw.go | 417 -------- x/distribution/types/tx.pb.go | 40 +- x/evidence/types/evidence.pb.go | 5 +- x/evidence/types/genesis.pb.go | 5 +- x/evidence/types/query.pb.go | 20 +- x/evidence/types/query.pb.gw.go | 95 -- x/evidence/types/tx.pb.go | 10 +- x/genutil/types/genesis.pb.go | 5 +- x/gov/types/genesis.pb.go | 5 +- x/gov/types/gov.pb.go | 40 +- x/gov/types/query.pb.go | 80 +- x/gov/types/query.pb.gw.go | 413 -------- x/gov/types/tx.pb.go | 30 +- .../applications/transfer/types/genesis.pb.go | 5 +- x/ibc/applications/transfer/types/query.pb.go | 30 +- .../transfer/types/query.pb.gw.go | 124 --- .../transfer/types/transfer.pb.go | 15 +- x/ibc/applications/transfer/types/tx.pb.go | 10 +- x/ibc/core/02-client/types/client.pb.go | 30 +- x/ibc/core/02-client/types/genesis.pb.go | 15 +- x/ibc/core/02-client/types/query.pb.go | 50 +- x/ibc/core/02-client/types/query.pb.gw.go | 254 ----- x/ibc/core/02-client/types/tx.pb.go | 40 +- .../core/03-connection/types/connection.pb.go | 30 +- x/ibc/core/03-connection/types/genesis.pb.go | 5 +- x/ibc/core/03-connection/types/query.pb.go | 50 +- x/ibc/core/03-connection/types/query.pb.gw.go | 258 ----- x/ibc/core/03-connection/types/tx.pb.go | 40 +- x/ibc/core/04-channel/types/channel.pb.go | 30 +- x/ibc/core/04-channel/types/genesis.pb.go | 10 +- x/ibc/core/04-channel/types/query.pb.go | 130 +-- x/ibc/core/04-channel/types/query.pb.gw.go | 945 ++---------------- x/ibc/core/04-channel/types/tx.pb.go | 100 +- .../core/23-commitment/types/commitment.pb.go | 20 +- x/ibc/core/types/genesis.pb.go | 5 +- .../06-solomachine/types/solomachine.pb.go | 80 +- .../07-tendermint/types/tendermint.pb.go | 25 +- .../09-localhost/types/localhost.pb.go | 5 +- x/mint/types/genesis.pb.go | 5 +- x/mint/types/mint.pb.go | 10 +- x/mint/types/query.pb.go | 30 +- x/mint/types/query.pb.gw.go | 99 -- x/params/types/proposal/params.pb.go | 10 +- x/params/types/proposal/query.pb.go | 10 +- x/params/types/proposal/query.pb.gw.go | 48 - x/slashing/types/genesis.pb.go | 20 +- x/slashing/types/query.pb.go | 30 +- x/slashing/types/query.pb.gw.go | 124 --- x/slashing/types/slashing.pb.go | 10 +- x/slashing/types/tx.pb.go | 10 +- x/staking/types/genesis.pb.go | 10 +- x/staking/types/query.pb.go | 140 +-- x/staking/types/query.pb.gw.go | 780 +-------------- x/staking/types/staking.pb.go | 100 +- x/staking/types/tx.pb.go | 50 +- x/upgrade/types/query.pb.go | 30 +- x/upgrade/types/query.pb.gw.go | 135 --- x/upgrade/types/upgrade.pb.go | 15 +- 102 files changed, 619 insertions(+), 6403 deletions(-) diff --git a/client/grpc/reflection/reflection.pb.go b/client/grpc/reflection/reflection.pb.go index 99878b2a342f..66dbef0c7105 100644 --- a/client/grpc/reflection/reflection.pb.go +++ b/client/grpc/reflection/reflection.pb.go @@ -589,10 +589,7 @@ func (m *ListAllInterfacesRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthReflection - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthReflection } if (iNdEx + skippy) > l { @@ -674,10 +671,7 @@ func (m *ListAllInterfacesResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthReflection - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthReflection } if (iNdEx + skippy) > l { @@ -759,10 +753,7 @@ func (m *ListImplementationsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthReflection - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthReflection } if (iNdEx + skippy) > l { @@ -844,10 +835,7 @@ func (m *ListImplementationsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthReflection - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthReflection } if (iNdEx + skippy) > l { diff --git a/client/grpc/reflection/reflection.pb.gw.go b/client/grpc/reflection/reflection.pb.gw.go index ab486750e860..255fdd4a794b 100644 --- a/client/grpc/reflection/reflection.pb.gw.go +++ b/client/grpc/reflection/reflection.pb.gw.go @@ -13,7 +13,6 @@ import ( "io" "net/http" - "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -23,13 +22,11 @@ import ( "google.golang.org/grpc/status" ) -// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage func request_ReflectionService_ListAllInterfaces_0(ctx context.Context, marshaler runtime.Marshaler, client ReflectionServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq ListAllInterfacesRequest @@ -40,15 +37,6 @@ func request_ReflectionService_ListAllInterfaces_0(ctx context.Context, marshale } -func local_request_ReflectionService_ListAllInterfaces_0(ctx context.Context, marshaler runtime.Marshaler, server ReflectionServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListAllInterfacesRequest - var metadata runtime.ServerMetadata - - msg, err := server.ListAllInterfaces(ctx, &protoReq) - return msg, metadata, err - -} - func request_ReflectionService_ListImplementations_0(ctx context.Context, marshaler runtime.Marshaler, client ReflectionServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq ListImplementationsRequest var metadata runtime.ServerMetadata @@ -76,82 +64,6 @@ func request_ReflectionService_ListImplementations_0(ctx context.Context, marsha } -func local_request_ReflectionService_ListImplementations_0(ctx context.Context, marshaler runtime.Marshaler, server ReflectionServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListImplementationsRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["interface_name"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "interface_name") - } - - protoReq.InterfaceName, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "interface_name", err) - } - - msg, err := server.ListImplementations(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterReflectionServiceHandlerServer registers the http handlers for service ReflectionService to "mux". -// UnaryRPC :call ReflectionServiceServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterReflectionServiceHandlerFromEndpoint instead. -func RegisterReflectionServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server ReflectionServiceServer) error { - - mux.Handle("GET", pattern_ReflectionService_ListAllInterfaces_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_ReflectionService_ListAllInterfaces_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_ReflectionService_ListAllInterfaces_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_ReflectionService_ListImplementations_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_ReflectionService_ListImplementations_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_ReflectionService_ListImplementations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - // RegisterReflectionServiceHandlerFromEndpoint is same as RegisterReflectionServiceHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterReflectionServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/client/grpc/tmservice/query.pb.go b/client/grpc/tmservice/query.pb.go index 0a27b4a2e517..8055c8c162aa 100644 --- a/client/grpc/tmservice/query.pb.go +++ b/client/grpc/tmservice/query.pb.go @@ -2202,10 +2202,7 @@ func (m *GetValidatorSetByHeightRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2344,10 +2341,7 @@ func (m *GetValidatorSetByHeightResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2433,10 +2427,7 @@ func (m *GetLatestValidatorSetRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2575,10 +2566,7 @@ func (m *GetLatestValidatorSetResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2734,10 +2722,7 @@ func (m *Validator) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2806,10 +2791,7 @@ func (m *GetBlockByHeightRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2931,10 +2913,7 @@ func (m *GetBlockByHeightResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2984,10 +2963,7 @@ func (m *GetLatestBlockRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3109,10 +3085,7 @@ func (m *GetLatestBlockResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3162,10 +3135,7 @@ func (m *GetSyncingRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3235,10 +3205,7 @@ func (m *GetSyncingResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3288,10 +3255,7 @@ func (m *GetNodeInfoRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3413,10 +3377,7 @@ func (m *GetNodeInfoResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3692,10 +3653,7 @@ func (m *VersionInfo) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3841,10 +3799,7 @@ func (m *Module) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { diff --git a/client/grpc/tmservice/query.pb.gw.go b/client/grpc/tmservice/query.pb.gw.go index 90135d79b937..429583a11a7e 100644 --- a/client/grpc/tmservice/query.pb.gw.go +++ b/client/grpc/tmservice/query.pb.gw.go @@ -13,7 +13,6 @@ import ( "io" "net/http" - "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -23,13 +22,11 @@ import ( "google.golang.org/grpc/status" ) -// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage func request_Service_GetNodeInfo_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetNodeInfoRequest @@ -40,15 +37,6 @@ func request_Service_GetNodeInfo_0(ctx context.Context, marshaler runtime.Marsha } -func local_request_Service_GetNodeInfo_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetNodeInfoRequest - var metadata runtime.ServerMetadata - - msg, err := server.GetNodeInfo(ctx, &protoReq) - return msg, metadata, err - -} - func request_Service_GetSyncing_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetSyncingRequest var metadata runtime.ServerMetadata @@ -58,15 +46,6 @@ func request_Service_GetSyncing_0(ctx context.Context, marshaler runtime.Marshal } -func local_request_Service_GetSyncing_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetSyncingRequest - var metadata runtime.ServerMetadata - - msg, err := server.GetSyncing(ctx, &protoReq) - return msg, metadata, err - -} - func request_Service_GetLatestBlock_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetLatestBlockRequest var metadata runtime.ServerMetadata @@ -76,15 +55,6 @@ func request_Service_GetLatestBlock_0(ctx context.Context, marshaler runtime.Mar } -func local_request_Service_GetLatestBlock_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetLatestBlockRequest - var metadata runtime.ServerMetadata - - msg, err := server.GetLatestBlock(ctx, &protoReq) - return msg, metadata, err - -} - func request_Service_GetBlockByHeight_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetBlockByHeightRequest var metadata runtime.ServerMetadata @@ -112,33 +82,6 @@ func request_Service_GetBlockByHeight_0(ctx context.Context, marshaler runtime.M } -func local_request_Service_GetBlockByHeight_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetBlockByHeightRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["height"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "height") - } - - protoReq.Height, err = runtime.Int64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "height", err) - } - - msg, err := server.GetBlockByHeight(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Service_GetLatestValidatorSet_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -159,22 +102,6 @@ func request_Service_GetLatestValidatorSet_0(ctx context.Context, marshaler runt } -func local_request_Service_GetLatestValidatorSet_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetLatestValidatorSetRequest - 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_Service_GetLatestValidatorSet_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetLatestValidatorSet(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Service_GetValidatorSetByHeight_0 = &utilities.DoubleArray{Encoding: map[string]int{"height": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -213,169 +140,6 @@ func request_Service_GetValidatorSetByHeight_0(ctx context.Context, marshaler ru } -func local_request_Service_GetValidatorSetByHeight_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetValidatorSetByHeightRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["height"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "height") - } - - protoReq.Height, err = runtime.Int64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "height", err) - } - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Service_GetValidatorSetByHeight_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetValidatorSetByHeight(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterServiceHandlerServer registers the http handlers for service Service to "mux". -// UnaryRPC :call ServiceServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterServiceHandlerFromEndpoint instead. -func RegisterServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server ServiceServer) error { - - mux.Handle("GET", pattern_Service_GetNodeInfo_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Service_GetNodeInfo_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Service_GetNodeInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Service_GetSyncing_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Service_GetSyncing_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Service_GetSyncing_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Service_GetLatestBlock_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Service_GetLatestBlock_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Service_GetLatestBlock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Service_GetBlockByHeight_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Service_GetBlockByHeight_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Service_GetBlockByHeight_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Service_GetLatestValidatorSet_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Service_GetLatestValidatorSet_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Service_GetLatestValidatorSet_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Service_GetValidatorSetByHeight_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Service_GetValidatorSetByHeight_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Service_GetValidatorSetByHeight_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - // RegisterServiceHandlerFromEndpoint is same as RegisterServiceHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/crypto/keys/ed25519/keys.pb.go b/crypto/keys/ed25519/keys.pb.go index 848dca4f47ed..35a98cf05861 100644 --- a/crypto/keys/ed25519/keys.pb.go +++ b/crypto/keys/ed25519/keys.pb.go @@ -314,10 +314,7 @@ func (m *PubKey) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthKeys - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthKeys } if (iNdEx + skippy) > l { @@ -401,10 +398,7 @@ func (m *PrivKey) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthKeys - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthKeys } if (iNdEx + skippy) > l { diff --git a/crypto/keys/multisig/keys.pb.go b/crypto/keys/multisig/keys.pb.go index 0dd70ae220bd..27ccf0fa5a27 100644 --- a/crypto/keys/multisig/keys.pb.go +++ b/crypto/keys/multisig/keys.pb.go @@ -258,10 +258,7 @@ func (m *LegacyAminoPubKey) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthKeys - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthKeys } if (iNdEx + skippy) > l { diff --git a/crypto/keys/secp256k1/keys.pb.go b/crypto/keys/secp256k1/keys.pb.go index 6dd45721bf4b..afcbab54b05d 100644 --- a/crypto/keys/secp256k1/keys.pb.go +++ b/crypto/keys/secp256k1/keys.pb.go @@ -313,10 +313,7 @@ func (m *PubKey) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthKeys - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthKeys } if (iNdEx + skippy) > l { @@ -400,10 +397,7 @@ func (m *PrivKey) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthKeys - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthKeys } if (iNdEx + skippy) > l { diff --git a/crypto/types/multisig.pb.go b/crypto/types/multisig.pb.go index 05b8b6977a9f..b9c907ade0a4 100644 --- a/crypto/types/multisig.pb.go +++ b/crypto/types/multisig.pb.go @@ -345,10 +345,7 @@ func (m *MultiSignature) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthMultisig - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthMultisig } if (iNdEx + skippy) > l { @@ -452,10 +449,7 @@ func (m *CompactBitArray) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthMultisig - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthMultisig } if (iNdEx + skippy) > l { diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 6c4f113995db..912c49fa9401 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -2222,8 +2222,8 @@ Service defines the gRPC querier service for tendermint queries. | `GetSyncing` | [GetSyncingRequest](#cosmos.base.tendermint.v1beta1.GetSyncingRequest) | [GetSyncingResponse](#cosmos.base.tendermint.v1beta1.GetSyncingResponse) | GetSyncing queries node syncing. | GET|/cosmos/base/tendermint/v1beta1/syncing| | `GetLatestBlock` | [GetLatestBlockRequest](#cosmos.base.tendermint.v1beta1.GetLatestBlockRequest) | [GetLatestBlockResponse](#cosmos.base.tendermint.v1beta1.GetLatestBlockResponse) | GetLatestBlock returns the latest block. | GET|/cosmos/base/tendermint/v1beta1/blocks/latest| | `GetBlockByHeight` | [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) | [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) | GetBlockByHeight queries block for given height. | GET|/cosmos/base/tendermint/v1beta1/blocks/{height}| -| `GetLatestValidatorSet` | [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) | [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) | GetLatestValidatorSet queries latest validator-set. | GET|/cosmos/base/tendermint/v1beta1/validators/latest| -| `GetValidatorSetByHeight` | [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) | [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) | GetValidatorSetByHeight queries validator-set at a given height. | GET|/cosmos/base/tendermint/v1beta1/validators/{height}| +| `GetLatestValidatorSet` | [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) | [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) | GetLatestValidatorSet queries latest validator-set. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/latest| +| `GetValidatorSetByHeight` | [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) | [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) | GetValidatorSetByHeight queries validator-set at a given height. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/{height}| diff --git a/go.mod b/go.mod index 417471e79de5..10577caa095a 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 github.com/gogo/gateway v1.1.0 - github.com/gogo/protobuf v1.3.2 + github.com/gogo/protobuf v1.3.3 github.com/golang/mock v1.4.4 github.com/golang/protobuf v1.4.3 github.com/golang/snappy v0.0.2 // indirect @@ -34,7 +34,7 @@ require ( github.com/prometheus/client_golang v1.8.0 github.com/prometheus/common v0.15.0 github.com/rakyll/statik v0.1.7 - github.com/regen-network/cosmos-proto v0.3.0 + github.com/regen-network/cosmos-proto v0.3.1 github.com/rs/zerolog v1.20.0 github.com/spf13/afero v1.3.4 // indirect github.com/spf13/cast v1.3.1 @@ -49,11 +49,10 @@ require ( github.com/tendermint/tendermint v0.34.2 github.com/tendermint/tm-db v0.6.3 golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad - golang.org/x/net v0.0.0-20200930145003-4acb6c075d10 // indirect - google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d + google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f google.golang.org/grpc v1.33.2 google.golang.org/protobuf v1.25.0 gopkg.in/yaml.v2 v2.4.0 ) -replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.2-alpha.regen.4 +replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 diff --git a/go.sum b/go.sum index 5d526fc85041..066d94520d06 100644 --- a/go.sum +++ b/go.sum @@ -322,7 +322,7 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d h1:Z+RDyXzjKE0i2sTjZ/b1uxiGtPhFy34Ou/Tk0qwN0kM= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= @@ -478,10 +478,10 @@ github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Ung github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/regen-network/cosmos-proto v0.3.0 h1:24dVpPrPi0GDoPVLesf2Ug98iK5QgVscPl0ga4Eoub0= -github.com/regen-network/cosmos-proto v0.3.0/go.mod h1:zuP2jVPHab6+IIyOx3nXHFN+euFNeS3W8XQkcdd4s7A= -github.com/regen-network/protobuf v1.3.2-alpha.regen.4 h1:c9jEnU+xm6vqyrQe3M94UFWqiXxRIKKnqBOh2EACmBE= -github.com/regen-network/protobuf v1.3.2-alpha.regen.4/go.mod h1:/J8/bR1T/NXyIdQDLUaq15LjNE83nRzkyrLAMcPewig= +github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg= +github.com/regen-network/cosmos-proto v0.3.1/go.mod h1:jO0sVX6a1B36nmE8C9xBFXpNwWejXC7QqCOnH3O0+YM= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -578,6 +578,8 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8= github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -641,6 +643,8 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -662,14 +666,15 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200930145003-4acb6c075d10 h1:YfxMZzv3PjGonQYNUaeU2+DhAdqOxerQ30JFB6WgAXo= -golang.org/x/net v0.0.0-20200930145003-4acb6c075d10/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -680,6 +685,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -718,6 +724,7 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM= @@ -733,7 +740,6 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -753,9 +759,11 @@ golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200110213125-a7a6caa82ab2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -791,8 +799,8 @@ google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4 h1:Rt0FRalMgdSlXAVJvX4pr65KfqaxHXSLkSJRD9pw6g0= google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d h1:HV9Z9qMhQEsdlvxNFELgQ11RkMzO3CMkjEySjCtuLes= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f h1:izedQ6yVIc5mZsRuXzmSreCOlzI0lCU1HpG8yEdMiKw= +google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= diff --git a/snapshots/types/snapshot.pb.go b/snapshots/types/snapshot.pb.go index 92fcb8151603..f37192f9c569 100644 --- a/snapshots/types/snapshot.pb.go +++ b/snapshots/types/snapshot.pb.go @@ -478,10 +478,7 @@ func (m *Snapshot) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSnapshot - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSnapshot } if (iNdEx + skippy) > l { @@ -563,10 +560,7 @@ func (m *Metadata) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSnapshot - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSnapshot } if (iNdEx + skippy) > l { diff --git a/store/types/commit_info.pb.go b/store/types/commit_info.pb.go index 5172e76d1712..988804d2f307 100644 --- a/store/types/commit_info.pb.go +++ b/store/types/commit_info.pb.go @@ -488,10 +488,7 @@ func (m *CommitInfo) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthCommitInfo - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthCommitInfo } if (iNdEx + skippy) > l { @@ -606,10 +603,7 @@ func (m *StoreInfo) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthCommitInfo - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthCommitInfo } if (iNdEx + skippy) > l { @@ -712,10 +706,7 @@ func (m *CommitID) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthCommitInfo - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthCommitInfo } if (iNdEx + skippy) > l { diff --git a/store/types/snapshot.pb.go b/store/types/snapshot.pb.go index 6450eeebcb4e..6f001da1bf28 100644 --- a/store/types/snapshot.pb.go +++ b/store/types/snapshot.pb.go @@ -605,10 +605,7 @@ func (m *SnapshotItem) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSnapshot - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSnapshot } if (iNdEx + skippy) > l { @@ -690,10 +687,7 @@ func (m *SnapshotStoreItem) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSnapshot - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSnapshot } if (iNdEx + skippy) > l { @@ -849,10 +843,7 @@ func (m *SnapshotIAVLItem) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSnapshot - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSnapshot } if (iNdEx + skippy) > l { diff --git a/testutil/testdata/query.pb.go b/testutil/testdata/query.pb.go index fc5f7af7cbae..e7d38dc7ceb8 100644 --- a/testutil/testdata/query.pb.go +++ b/testutil/testdata/query.pb.go @@ -834,10 +834,7 @@ func (m *EchoRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -919,10 +916,7 @@ func (m *EchoResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1004,10 +998,7 @@ func (m *SayHelloRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1089,10 +1080,7 @@ func (m *SayHelloResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1178,10 +1166,7 @@ func (m *TestAnyRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1267,10 +1252,7 @@ func (m *TestAnyResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { diff --git a/testutil/testdata/testdata.pb.go b/testutil/testdata/testdata.pb.go index 3c5b44e7a464..400e64936810 100644 --- a/testutil/testdata/testdata.pb.go +++ b/testutil/testdata/testdata.pb.go @@ -798,10 +798,7 @@ func (m *Dog) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTestdata - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTestdata } if (iNdEx + skippy) > l { @@ -902,10 +899,7 @@ func (m *Cat) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTestdata - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTestdata } if (iNdEx + skippy) > l { @@ -1010,10 +1004,7 @@ func (m *HasAnimal) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTestdata - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTestdata } if (iNdEx + skippy) > l { @@ -1099,10 +1090,7 @@ func (m *HasHasAnimal) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTestdata - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTestdata } if (iNdEx + skippy) > l { @@ -1188,10 +1176,7 @@ func (m *HasHasHasAnimal) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTestdata - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTestdata } if (iNdEx + skippy) > l { @@ -1307,10 +1292,7 @@ func (m *BadMultiSignature) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTestdata - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTestdata } if (iNdEx + skippy) > l { diff --git a/testutil/testdata/tx.pb.go b/testutil/testdata/tx.pb.go index 3b0530fe4617..694a045fffae 100644 --- a/testutil/testdata/tx.pb.go +++ b/testutil/testdata/tx.pb.go @@ -490,10 +490,7 @@ func (m *MsgCreateDog) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -575,10 +572,7 @@ func (m *MsgCreateDogResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -660,10 +654,7 @@ func (m *TestMsg) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { diff --git a/testutil/testdata/unknonwnproto.pb.go b/testutil/testdata/unknonwnproto.pb.go index b8a5425e873a..eb4abf1fff10 100644 --- a/testutil/testdata/unknonwnproto.pb.go +++ b/testutil/testdata/unknonwnproto.pb.go @@ -6623,10 +6623,7 @@ func (m *Customer1) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -6831,10 +6828,7 @@ func (m *Customer2) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -6935,10 +6929,7 @@ func (m *Nested4A) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -7171,7 +7162,7 @@ func (m *Nested3A) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > postIndex { @@ -7188,10 +7179,7 @@ func (m *Nested3A) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -7328,10 +7316,7 @@ func (m *Nested2A) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -7436,10 +7421,7 @@ func (m *Nested1A) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -7559,10 +7541,7 @@ func (m *Nested4B) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -7716,10 +7695,7 @@ func (m *Nested3B) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -7867,10 +7843,7 @@ func (m *Nested2B) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -7994,10 +7967,7 @@ func (m *Nested1B) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -8252,10 +8222,7 @@ func (m *Customer3) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -8625,10 +8592,7 @@ func (m *TestVersion1) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -9017,10 +8981,7 @@ func (m *TestVersion2) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -9422,10 +9383,7 @@ func (m *TestVersion3) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -9792,10 +9750,7 @@ func (m *TestVersion3LoneOneOfValue) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -10249,10 +10204,7 @@ func (m *TestVersion3LoneNesting) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -10389,10 +10341,7 @@ func (m *TestVersion3LoneNesting_Inner1) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -10506,10 +10455,7 @@ func (m *TestVersion3LoneNesting_Inner1_InnerInner) Unmarshal(dAtA []byte) error if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -10659,10 +10605,7 @@ func (m *TestVersion3LoneNesting_Inner2) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -10776,10 +10719,7 @@ func (m *TestVersion3LoneNesting_Inner2_InnerInner) Unmarshal(dAtA []byte) error if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -11233,10 +11173,7 @@ func (m *TestVersion4LoneNesting) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -11373,10 +11310,7 @@ func (m *TestVersion4LoneNesting_Inner1) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -11477,10 +11411,7 @@ func (m *TestVersion4LoneNesting_Inner1_InnerInner) Unmarshal(dAtA []byte) error if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -11630,10 +11561,7 @@ func (m *TestVersion4LoneNesting_Inner2) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -11734,10 +11662,7 @@ func (m *TestVersion4LoneNesting_Inner2_InnerInner) Unmarshal(dAtA []byte) error if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -11967,10 +11892,7 @@ func (m *TestVersionFD1) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -12200,10 +12122,7 @@ func (m *TestVersionFD1WithExtraAny) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -12327,10 +12246,7 @@ func (m *AnyWithExtra) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -12548,10 +12464,7 @@ func (m *TestUpdatedTxRaw) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -12805,10 +12718,7 @@ func (m *TestUpdatedTxBody) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -12996,10 +12906,7 @@ func (m *TestUpdatedAuthInfo) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { @@ -13125,10 +13032,7 @@ func (m *TestRepeatedUints) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUnknonwnproto - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUnknonwnproto } if (iNdEx + skippy) > l { diff --git a/types/abci.pb.go b/types/abci.pb.go index c17680722e28..44b35c3536d8 100644 --- a/types/abci.pb.go +++ b/types/abci.pb.go @@ -1881,10 +1881,7 @@ func (m *TxResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthAbci - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthAbci } if (iNdEx + skippy) > l { @@ -2019,10 +2016,7 @@ func (m *ABCIMessageLog) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthAbci - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthAbci } if (iNdEx + skippy) > l { @@ -2138,10 +2132,7 @@ func (m *StringEvent) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthAbci - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthAbci } if (iNdEx + skippy) > l { @@ -2255,10 +2246,7 @@ func (m *Attribute) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthAbci - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthAbci } if (iNdEx + skippy) > l { @@ -2346,10 +2334,7 @@ func (m *GasInfo) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthAbci - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthAbci } if (iNdEx + skippy) > l { @@ -2499,10 +2484,7 @@ func (m *Result) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthAbci - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthAbci } if (iNdEx + skippy) > l { @@ -2621,10 +2603,7 @@ func (m *SimulationResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthAbci - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthAbci } if (iNdEx + skippy) > l { @@ -2740,10 +2719,7 @@ func (m *MsgData) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthAbci - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthAbci } if (iNdEx + skippy) > l { @@ -2827,10 +2803,7 @@ func (m *TxMsgData) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthAbci - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthAbci } if (iNdEx + skippy) > l { @@ -3009,10 +2982,7 @@ func (m *SearchTxsResult) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthAbci - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthAbci } if (iNdEx + skippy) > l { diff --git a/types/coin.pb.go b/types/coin.pb.go index ba4bb444da01..df8d34d4f9d5 100644 --- a/types/coin.pb.go +++ b/types/coin.pb.go @@ -593,10 +593,7 @@ func (m *Coin) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthCoin - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthCoin } if (iNdEx + skippy) > l { @@ -712,10 +709,7 @@ func (m *DecCoin) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthCoin - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthCoin } if (iNdEx + skippy) > l { @@ -799,10 +793,7 @@ func (m *IntProto) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthCoin - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthCoin } if (iNdEx + skippy) > l { @@ -886,10 +877,7 @@ func (m *DecProto) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthCoin - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthCoin } if (iNdEx + skippy) > l { diff --git a/types/kv/kv.pb.go b/types/kv/kv.pb.go index 982324881d07..eedb948bf5ae 100644 --- a/types/kv/kv.pb.go +++ b/types/kv/kv.pb.go @@ -338,10 +338,7 @@ func (m *Pairs) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthKv - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthKv } if (iNdEx + skippy) > l { @@ -459,10 +456,7 @@ func (m *Pair) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthKv - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthKv } if (iNdEx + skippy) > l { diff --git a/types/query/pagination.pb.go b/types/query/pagination.pb.go index 0a404696d72e..b27db91746a5 100644 --- a/types/query/pagination.pb.go +++ b/types/query/pagination.pb.go @@ -469,10 +469,7 @@ func (m *PageRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthPagination - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthPagination } if (iNdEx + skippy) > l { @@ -575,10 +572,7 @@ func (m *PageResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthPagination - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthPagination } if (iNdEx + skippy) > l { diff --git a/types/tx/service.pb.go b/types/tx/service.pb.go index 57f1f627635e..f01a60fe52a9 100644 --- a/types/tx/service.pb.go +++ b/types/tx/service.pb.go @@ -1348,10 +1348,7 @@ func (m *GetTxsEventRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthService - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthService } if (iNdEx + skippy) > l { @@ -1505,10 +1502,7 @@ func (m *GetTxsEventResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthService - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthService } if (iNdEx + skippy) > l { @@ -1611,10 +1605,7 @@ func (m *BroadcastTxRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthService - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthService } if (iNdEx + skippy) > l { @@ -1700,10 +1691,7 @@ func (m *BroadcastTxResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthService - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthService } if (iNdEx + skippy) > l { @@ -1789,10 +1777,7 @@ func (m *SimulateRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthService - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthService } if (iNdEx + skippy) > l { @@ -1914,10 +1899,7 @@ func (m *SimulateResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthService - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthService } if (iNdEx + skippy) > l { @@ -1999,10 +1981,7 @@ func (m *GetTxRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthService - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthService } if (iNdEx + skippy) > l { @@ -2124,10 +2103,7 @@ func (m *GetTxResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthService - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthService } if (iNdEx + skippy) > l { diff --git a/types/tx/service.pb.gw.go b/types/tx/service.pb.gw.go index 6d94c423ecbd..59f6e572d9b7 100644 --- a/types/tx/service.pb.gw.go +++ b/types/tx/service.pb.gw.go @@ -13,7 +13,6 @@ import ( "io" "net/http" - "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -23,13 +22,11 @@ import ( "google.golang.org/grpc/status" ) -// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage func request_Service_Simulate_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq SimulateRequest @@ -48,23 +45,6 @@ func request_Service_Simulate_0(ctx context.Context, marshaler runtime.Marshaler } -func local_request_Service_Simulate_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SimulateRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.Simulate(ctx, &protoReq) - return msg, metadata, err - -} - func request_Service_GetTx_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetTxRequest var metadata runtime.ServerMetadata @@ -92,33 +72,6 @@ func request_Service_GetTx_0(ctx context.Context, marshaler runtime.Marshaler, c } -func local_request_Service_GetTx_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetTxRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["hash"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "hash") - } - - protoReq.Hash, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "hash", err) - } - - msg, err := server.GetTx(ctx, &protoReq) - return msg, metadata, err - -} - func request_Service_BroadcastTx_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq BroadcastTxRequest var metadata runtime.ServerMetadata @@ -136,23 +89,6 @@ func request_Service_BroadcastTx_0(ctx context.Context, marshaler runtime.Marsha } -func local_request_Service_BroadcastTx_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq BroadcastTxRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.BroadcastTx(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Service_GetTxsEvent_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -173,111 +109,6 @@ func request_Service_GetTxsEvent_0(ctx context.Context, marshaler runtime.Marsha } -func local_request_Service_GetTxsEvent_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetTxsEventRequest - 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_Service_GetTxsEvent_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetTxsEvent(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterServiceHandlerServer registers the http handlers for service Service to "mux". -// UnaryRPC :call ServiceServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterServiceHandlerFromEndpoint instead. -func RegisterServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server ServiceServer) error { - - mux.Handle("POST", pattern_Service_Simulate_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Service_Simulate_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Service_Simulate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Service_GetTx_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Service_GetTx_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Service_GetTx_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Service_BroadcastTx_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Service_BroadcastTx_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Service_BroadcastTx_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Service_GetTxsEvent_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Service_GetTxsEvent_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Service_GetTxsEvent_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - // RegisterServiceHandlerFromEndpoint is same as RegisterServiceHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/types/tx/signing/signing.pb.go b/types/tx/signing/signing.pb.go index 424e7395df30..f06a270c7cbd 100644 --- a/types/tx/signing/signing.pb.go +++ b/types/tx/signing/signing.pb.go @@ -867,10 +867,7 @@ func (m *SignatureDescriptors) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSigning - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSigning } if (iNdEx + skippy) > l { @@ -1011,10 +1008,7 @@ func (m *SignatureDescriptor) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSigning - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSigning } if (iNdEx + skippy) > l { @@ -1134,10 +1128,7 @@ func (m *SignatureDescriptor_Data) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSigning - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSigning } if (iNdEx + skippy) > l { @@ -1240,10 +1231,7 @@ func (m *SignatureDescriptor_Data_Single) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSigning - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSigning } if (iNdEx + skippy) > l { @@ -1363,10 +1351,7 @@ func (m *SignatureDescriptor_Data_Multi) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSigning - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSigning } if (iNdEx + skippy) > l { diff --git a/types/tx/tx.pb.go b/types/tx/tx.pb.go index 750f4266f3fa..a552c7a083e1 100644 --- a/types/tx/tx.pb.go +++ b/types/tx/tx.pb.go @@ -1746,10 +1746,7 @@ func (m *Tx) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1899,10 +1896,7 @@ func (m *TxRaw) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2071,10 +2065,7 @@ func (m *SignDoc) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2277,10 +2268,7 @@ func (m *TxBody) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2400,10 +2388,7 @@ func (m *AuthInfo) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2544,10 +2529,7 @@ func (m *SignerInfo) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2667,10 +2649,7 @@ func (m *ModeInfo) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2739,10 +2718,7 @@ func (m *ModeInfo_Single) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2862,10 +2838,7 @@ func (m *ModeInfo_Multi) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -3032,10 +3005,7 @@ func (m *Fee) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { diff --git a/x/auth/types/auth.pb.go b/x/auth/types/auth.pb.go index 4a05cf8158e7..fa52ac5a8b90 100644 --- a/x/auth/types/auth.pb.go +++ b/x/auth/types/auth.pb.go @@ -652,10 +652,7 @@ func (m *BaseAccount) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthAuth - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthAuth } if (iNdEx + skippy) > l { @@ -805,10 +802,7 @@ func (m *ModuleAccount) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthAuth - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthAuth } if (iNdEx + skippy) > l { @@ -953,10 +947,7 @@ func (m *Params) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthAuth - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthAuth } if (iNdEx + skippy) > l { diff --git a/x/auth/types/genesis.pb.go b/x/auth/types/genesis.pb.go index 3af036f4f450..4e7396ab7cb3 100644 --- a/x/auth/types/genesis.pb.go +++ b/x/auth/types/genesis.pb.go @@ -288,10 +288,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { diff --git a/x/auth/types/query.pb.go b/x/auth/types/query.pb.go index ff8be08a3ff6..fcb0efa96614 100644 --- a/x/auth/types/query.pb.go +++ b/x/auth/types/query.pb.go @@ -610,10 +610,7 @@ func (m *QueryAccountRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -699,10 +696,7 @@ func (m *QueryAccountResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -752,10 +746,7 @@ func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -838,10 +829,7 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { diff --git a/x/auth/types/query.pb.gw.go b/x/auth/types/query.pb.gw.go index 0525b9c15364..af50b8afa3c4 100644 --- a/x/auth/types/query.pb.gw.go +++ b/x/auth/types/query.pb.gw.go @@ -13,7 +13,6 @@ import ( "io" "net/http" - "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -23,13 +22,11 @@ import ( "google.golang.org/grpc/status" ) -// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage func request_Query_Account_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryAccountRequest @@ -58,33 +55,6 @@ func request_Query_Account_0(ctx context.Context, marshaler runtime.Marshaler, c } -func local_request_Query_Account_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryAccountRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["address"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") - } - - protoReq.Address, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) - } - - msg, err := server.Account(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryParamsRequest var metadata runtime.ServerMetadata @@ -94,64 +64,6 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } -func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryParamsRequest - var metadata runtime.ServerMetadata - - msg, err := server.Params(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". -// UnaryRPC :call QueryServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. -func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { - - mux.Handle("GET", pattern_Query_Account_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Account_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Account_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/auth/vesting/types/tx.pb.go b/x/auth/vesting/types/tx.pb.go index ab3283c238aa..d07a154dd326 100644 --- a/x/auth/vesting/types/tx.pb.go +++ b/x/auth/vesting/types/tx.pb.go @@ -624,10 +624,7 @@ func (m *MsgCreateVestingAccount) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -677,10 +674,7 @@ func (m *MsgCreateVestingAccountResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { diff --git a/x/auth/vesting/types/vesting.pb.go b/x/auth/vesting/types/vesting.pb.go index c491c7504b51..7672ce66f8e0 100644 --- a/x/auth/vesting/types/vesting.pb.go +++ b/x/auth/vesting/types/vesting.pb.go @@ -857,10 +857,7 @@ func (m *BaseVestingAccount) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthVesting - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthVesting } if (iNdEx + skippy) > l { @@ -965,10 +962,7 @@ func (m *ContinuousVestingAccount) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthVesting - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthVesting } if (iNdEx + skippy) > l { @@ -1054,10 +1048,7 @@ func (m *DelayedVestingAccount) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthVesting - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthVesting } if (iNdEx + skippy) > l { @@ -1160,10 +1151,7 @@ func (m *Period) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthVesting - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthVesting } if (iNdEx + skippy) > l { @@ -1302,10 +1290,7 @@ func (m *PeriodicVestingAccount) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthVesting - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthVesting } if (iNdEx + skippy) > l { diff --git a/x/bank/types/bank.pb.go b/x/bank/types/bank.pb.go index ee27ea2cab57..ef1c52c1ccb5 100644 --- a/x/bank/types/bank.pb.go +++ b/x/bank/types/bank.pb.go @@ -1054,10 +1054,7 @@ func (m *Params) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthBank - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthBank } if (iNdEx + skippy) > l { @@ -1159,10 +1156,7 @@ func (m *SendEnabled) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthBank - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthBank } if (iNdEx + skippy) > l { @@ -1278,10 +1272,7 @@ func (m *Input) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthBank - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthBank } if (iNdEx + skippy) > l { @@ -1397,10 +1388,7 @@ func (m *Output) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthBank - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthBank } if (iNdEx + skippy) > l { @@ -1484,10 +1472,7 @@ func (m *Supply) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthBank - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthBank } if (iNdEx + skippy) > l { @@ -1620,10 +1605,7 @@ func (m *DenomUnit) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthBank - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthBank } if (iNdEx + skippy) > l { @@ -1803,10 +1785,7 @@ func (m *Metadata) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthBank - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthBank } if (iNdEx + skippy) > l { diff --git a/x/bank/types/genesis.pb.go b/x/bank/types/genesis.pb.go index a4b6f8b185ec..f1d124bdd4e6 100644 --- a/x/bank/types/genesis.pb.go +++ b/x/bank/types/genesis.pb.go @@ -529,10 +529,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { @@ -648,10 +645,7 @@ func (m *Balance) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { diff --git a/x/bank/types/query.pb.go b/x/bank/types/query.pb.go index 0af6dac36dec..8d07c80787fc 100644 --- a/x/bank/types/query.pb.go +++ b/x/bank/types/query.pb.go @@ -1363,10 +1363,7 @@ func (m *QueryBalanceRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1452,10 +1449,7 @@ func (m *QueryBalanceResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1573,10 +1567,7 @@ func (m *QueryAllBalancesRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1696,10 +1687,7 @@ func (m *QueryAllBalancesResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1749,10 +1737,7 @@ func (m *QueryTotalSupplyRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1836,10 +1821,7 @@ func (m *QueryTotalSupplyResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1921,10 +1903,7 @@ func (m *QuerySupplyOfRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2007,10 +1986,7 @@ func (m *QuerySupplyOfResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2060,10 +2036,7 @@ func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2146,10 +2119,7 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { diff --git a/x/bank/types/query.pb.gw.go b/x/bank/types/query.pb.gw.go index b1c6372ab7c1..da70a5cc1995 100644 --- a/x/bank/types/query.pb.gw.go +++ b/x/bank/types/query.pb.gw.go @@ -13,7 +13,6 @@ import ( "io" "net/http" - "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -23,13 +22,11 @@ import ( "google.golang.org/grpc/status" ) -// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage func request_Query_Balance_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryBalanceRequest @@ -69,44 +66,6 @@ func request_Query_Balance_0(ctx context.Context, marshaler runtime.Marshaler, c } -func local_request_Query_Balance_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryBalanceRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["address"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") - } - - protoReq.Address, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) - } - - val, ok = pathParams["denom"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom") - } - - protoReq.Denom, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err) - } - - msg, err := server.Balance(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_AllBalances_0 = &utilities.DoubleArray{Encoding: map[string]int{"address": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -145,40 +104,6 @@ func request_Query_AllBalances_0(ctx context.Context, marshaler runtime.Marshale } -func local_request_Query_AllBalances_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryAllBalancesRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["address"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") - } - - protoReq.Address, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) - } - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_AllBalances_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.AllBalances(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_TotalSupply_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryTotalSupplyRequest var metadata runtime.ServerMetadata @@ -188,15 +113,6 @@ func request_Query_TotalSupply_0(ctx context.Context, marshaler runtime.Marshale } -func local_request_Query_TotalSupply_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryTotalSupplyRequest - var metadata runtime.ServerMetadata - - msg, err := server.TotalSupply(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_SupplyOf_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QuerySupplyOfRequest var metadata runtime.ServerMetadata @@ -224,33 +140,6 @@ func request_Query_SupplyOf_0(ctx context.Context, marshaler runtime.Marshaler, } -func local_request_Query_SupplyOf_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QuerySupplyOfRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["denom"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom") - } - - protoReq.Denom, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err) - } - - msg, err := server.SupplyOf(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryParamsRequest var metadata runtime.ServerMetadata @@ -260,124 +149,6 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } -func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryParamsRequest - var metadata runtime.ServerMetadata - - msg, err := server.Params(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". -// UnaryRPC :call QueryServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. -func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { - - mux.Handle("GET", pattern_Query_Balance_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Balance_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Balance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_AllBalances_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_AllBalances_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_AllBalances_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_TotalSupply_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_TotalSupply_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_TotalSupply_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_SupplyOf_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_SupplyOf_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_SupplyOf_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/bank/types/tx.pb.go b/x/bank/types/tx.pb.go index a9e70007c389..6dd52c4b64d8 100644 --- a/x/bank/types/tx.pb.go +++ b/x/bank/types/tx.pb.go @@ -718,10 +718,7 @@ func (m *MsgSend) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -771,10 +768,7 @@ func (m *MsgSendResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -892,10 +886,7 @@ func (m *MsgMultiSend) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -945,10 +936,7 @@ func (m *MsgMultiSendResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { diff --git a/x/capability/types/capability.pb.go b/x/capability/types/capability.pb.go index 2fb8308714b5..785742bd338a 100644 --- a/x/capability/types/capability.pb.go +++ b/x/capability/types/capability.pb.go @@ -403,10 +403,7 @@ func (m *Capability) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthCapability - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthCapability } if (iNdEx + skippy) > l { @@ -520,10 +517,7 @@ func (m *Owner) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthCapability - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthCapability } if (iNdEx + skippy) > l { @@ -607,10 +601,7 @@ func (m *CapabilityOwners) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthCapability - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthCapability } if (iNdEx + skippy) > l { diff --git a/x/capability/types/genesis.pb.go b/x/capability/types/genesis.pb.go index 4b79d4039082..e72c18eda53b 100644 --- a/x/capability/types/genesis.pb.go +++ b/x/capability/types/genesis.pb.go @@ -381,10 +381,7 @@ func (m *GenesisOwners) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { @@ -487,10 +484,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { diff --git a/x/crisis/types/genesis.pb.go b/x/crisis/types/genesis.pb.go index 472f5677b900..06a870ff7193 100644 --- a/x/crisis/types/genesis.pb.go +++ b/x/crisis/types/genesis.pb.go @@ -227,10 +227,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { diff --git a/x/crisis/types/tx.pb.go b/x/crisis/types/tx.pb.go index 7fed79516c1c..f84c4adbf106 100644 --- a/x/crisis/types/tx.pb.go +++ b/x/crisis/types/tx.pb.go @@ -463,10 +463,7 @@ func (m *MsgVerifyInvariant) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -516,10 +513,7 @@ func (m *MsgVerifyInvariantResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { diff --git a/x/distribution/types/distribution.pb.go b/x/distribution/types/distribution.pb.go index 44e51876d7ad..2657160a6ea0 100644 --- a/x/distribution/types/distribution.pb.go +++ b/x/distribution/types/distribution.pb.go @@ -1965,10 +1965,7 @@ func (m *Params) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthDistribution - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthDistribution } if (iNdEx + skippy) > l { @@ -2071,10 +2068,7 @@ func (m *ValidatorHistoricalRewards) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthDistribution - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthDistribution } if (iNdEx + skippy) > l { @@ -2177,10 +2171,7 @@ func (m *ValidatorCurrentRewards) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthDistribution - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthDistribution } if (iNdEx + skippy) > l { @@ -2264,10 +2255,7 @@ func (m *ValidatorAccumulatedCommission) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthDistribution - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthDistribution } if (iNdEx + skippy) > l { @@ -2351,10 +2339,7 @@ func (m *ValidatorOutstandingRewards) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthDistribution - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthDistribution } if (iNdEx + skippy) > l { @@ -2457,10 +2442,7 @@ func (m *ValidatorSlashEvent) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthDistribution - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthDistribution } if (iNdEx + skippy) > l { @@ -2544,10 +2526,7 @@ func (m *ValidatorSlashEvents) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthDistribution - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthDistribution } if (iNdEx + skippy) > l { @@ -2631,10 +2610,7 @@ func (m *FeePool) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthDistribution - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthDistribution } if (iNdEx + skippy) > l { @@ -2814,10 +2790,7 @@ func (m *CommunityPoolSpendProposal) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthDistribution - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthDistribution } if (iNdEx + skippy) > l { @@ -2939,10 +2912,7 @@ func (m *DelegatorStartingInfo) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthDistribution - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthDistribution } if (iNdEx + skippy) > l { @@ -3058,10 +3028,7 @@ func (m *DelegationDelegatorReward) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthDistribution - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthDistribution } if (iNdEx + skippy) > l { @@ -3271,10 +3238,7 @@ func (m *CommunityPoolSpendProposalWithDeposit) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthDistribution - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthDistribution } if (iNdEx + skippy) > l { diff --git a/x/distribution/types/genesis.pb.go b/x/distribution/types/genesis.pb.go index 04069c435a0d..5c94d4359ffa 100644 --- a/x/distribution/types/genesis.pb.go +++ b/x/distribution/types/genesis.pb.go @@ -1214,10 +1214,7 @@ func (m *DelegatorWithdrawInfo) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { @@ -1333,10 +1330,7 @@ func (m *ValidatorOutstandingRewardsRecord) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { @@ -1451,10 +1445,7 @@ func (m *ValidatorAccumulatedCommissionRecord) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { @@ -1588,10 +1579,7 @@ func (m *ValidatorHistoricalRewardsRecord) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { @@ -1706,10 +1694,7 @@ func (m *ValidatorCurrentRewardsRecord) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { @@ -1856,10 +1841,7 @@ func (m *DelegatorStartingInfoRecord) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { @@ -2012,10 +1994,7 @@ func (m *ValidatorSlashEventRecord) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { @@ -2401,10 +2380,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { diff --git a/x/distribution/types/query.pb.go b/x/distribution/types/query.pb.go index e527c0045d15..47acd5e73c52 100644 --- a/x/distribution/types/query.pb.go +++ b/x/distribution/types/query.pb.go @@ -2250,10 +2250,7 @@ func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2336,10 +2333,7 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2421,10 +2415,7 @@ func (m *QueryValidatorOutstandingRewardsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2507,10 +2498,7 @@ func (m *QueryValidatorOutstandingRewardsResponse) Unmarshal(dAtA []byte) error if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2592,10 +2580,7 @@ func (m *QueryValidatorCommissionRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2678,10 +2663,7 @@ func (m *QueryValidatorCommissionResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2837,10 +2819,7 @@ func (m *QueryValidatorSlashesRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2960,10 +2939,7 @@ func (m *QueryValidatorSlashesResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3077,10 +3053,7 @@ func (m *QueryDelegationRewardsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3164,10 +3137,7 @@ func (m *QueryDelegationRewardsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3249,10 +3219,7 @@ func (m *QueryDelegationTotalRewardsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3370,10 +3337,7 @@ func (m *QueryDelegationTotalRewardsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3455,10 +3419,7 @@ func (m *QueryDelegatorValidatorsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3540,10 +3501,7 @@ func (m *QueryDelegatorValidatorsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3625,10 +3583,7 @@ func (m *QueryDelegatorWithdrawAddressRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3710,10 +3665,7 @@ func (m *QueryDelegatorWithdrawAddressResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3763,10 +3715,7 @@ func (m *QueryCommunityPoolRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3850,10 +3799,7 @@ func (m *QueryCommunityPoolResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { diff --git a/x/distribution/types/query.pb.gw.go b/x/distribution/types/query.pb.gw.go index 7bbe7b7a29fb..416aee29c94c 100644 --- a/x/distribution/types/query.pb.gw.go +++ b/x/distribution/types/query.pb.gw.go @@ -13,7 +13,6 @@ import ( "io" "net/http" - "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -23,13 +22,11 @@ import ( "google.golang.org/grpc/status" ) -// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryParamsRequest @@ -40,15 +37,6 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } -func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryParamsRequest - var metadata runtime.ServerMetadata - - msg, err := server.Params(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_ValidatorOutstandingRewards_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryValidatorOutstandingRewardsRequest var metadata runtime.ServerMetadata @@ -76,33 +64,6 @@ func request_Query_ValidatorOutstandingRewards_0(ctx context.Context, marshaler } -func local_request_Query_ValidatorOutstandingRewards_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryValidatorOutstandingRewardsRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["validator_address"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_address") - } - - protoReq.ValidatorAddress, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_address", err) - } - - msg, err := server.ValidatorOutstandingRewards(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_ValidatorCommission_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryValidatorCommissionRequest var metadata runtime.ServerMetadata @@ -130,33 +91,6 @@ func request_Query_ValidatorCommission_0(ctx context.Context, marshaler runtime. } -func local_request_Query_ValidatorCommission_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryValidatorCommissionRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["validator_address"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_address") - } - - protoReq.ValidatorAddress, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_address", err) - } - - msg, err := server.ValidatorCommission(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_ValidatorSlashes_0 = &utilities.DoubleArray{Encoding: map[string]int{"validator_address": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -195,40 +129,6 @@ func request_Query_ValidatorSlashes_0(ctx context.Context, marshaler runtime.Mar } -func local_request_Query_ValidatorSlashes_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryValidatorSlashesRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["validator_address"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_address") - } - - protoReq.ValidatorAddress, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_address", err) - } - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ValidatorSlashes_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ValidatorSlashes(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_DelegationRewards_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryDelegationRewardsRequest var metadata runtime.ServerMetadata @@ -267,44 +167,6 @@ func request_Query_DelegationRewards_0(ctx context.Context, marshaler runtime.Ma } -func local_request_Query_DelegationRewards_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDelegationRewardsRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["delegator_address"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_address") - } - - protoReq.DelegatorAddress, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_address", err) - } - - val, ok = pathParams["validator_address"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_address") - } - - protoReq.ValidatorAddress, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_address", err) - } - - msg, err := server.DelegationRewards(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_DelegationTotalRewards_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryDelegationTotalRewardsRequest var metadata runtime.ServerMetadata @@ -332,33 +194,6 @@ func request_Query_DelegationTotalRewards_0(ctx context.Context, marshaler runti } -func local_request_Query_DelegationTotalRewards_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDelegationTotalRewardsRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["delegator_address"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_address") - } - - protoReq.DelegatorAddress, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_address", err) - } - - msg, err := server.DelegationTotalRewards(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_DelegatorValidators_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryDelegatorValidatorsRequest var metadata runtime.ServerMetadata @@ -386,33 +221,6 @@ func request_Query_DelegatorValidators_0(ctx context.Context, marshaler runtime. } -func local_request_Query_DelegatorValidators_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDelegatorValidatorsRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["delegator_address"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_address") - } - - protoReq.DelegatorAddress, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_address", err) - } - - msg, err := server.DelegatorValidators(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_DelegatorWithdrawAddress_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryDelegatorWithdrawAddressRequest var metadata runtime.ServerMetadata @@ -440,33 +248,6 @@ func request_Query_DelegatorWithdrawAddress_0(ctx context.Context, marshaler run } -func local_request_Query_DelegatorWithdrawAddress_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDelegatorWithdrawAddressRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["delegator_address"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_address") - } - - protoReq.DelegatorAddress, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_address", err) - } - - msg, err := server.DelegatorWithdrawAddress(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_CommunityPool_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryCommunityPoolRequest var metadata runtime.ServerMetadata @@ -476,204 +257,6 @@ func request_Query_CommunityPool_0(ctx context.Context, marshaler runtime.Marsha } -func local_request_Query_CommunityPool_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryCommunityPoolRequest - var metadata runtime.ServerMetadata - - msg, err := server.CommunityPool(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". -// UnaryRPC :call QueryServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. -func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { - - mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_ValidatorOutstandingRewards_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_ValidatorOutstandingRewards_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ValidatorOutstandingRewards_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_ValidatorCommission_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_ValidatorCommission_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ValidatorCommission_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_ValidatorSlashes_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_ValidatorSlashes_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ValidatorSlashes_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_DelegationRewards_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_DelegationRewards_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_DelegationRewards_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_DelegationTotalRewards_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_DelegationTotalRewards_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_DelegationTotalRewards_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_DelegatorValidators_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_DelegatorValidators_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_DelegatorValidators_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_DelegatorWithdrawAddress_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_DelegatorWithdrawAddress_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_DelegatorWithdrawAddress_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_CommunityPool_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_CommunityPool_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_CommunityPool_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/distribution/types/tx.pb.go b/x/distribution/types/tx.pb.go index 7748badacf4f..55cfce4e78f4 100644 --- a/x/distribution/types/tx.pb.go +++ b/x/distribution/types/tx.pb.go @@ -1140,10 +1140,7 @@ func (m *MsgSetWithdrawAddress) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1193,10 +1190,7 @@ func (m *MsgSetWithdrawAddressResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1310,10 +1304,7 @@ func (m *MsgWithdrawDelegatorReward) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1363,10 +1354,7 @@ func (m *MsgWithdrawDelegatorRewardResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1448,10 +1436,7 @@ func (m *MsgWithdrawValidatorCommission) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1501,10 +1486,7 @@ func (m *MsgWithdrawValidatorCommissionResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1620,10 +1602,7 @@ func (m *MsgFundCommunityPool) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1673,10 +1652,7 @@ func (m *MsgFundCommunityPoolResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { diff --git a/x/evidence/types/evidence.pb.go b/x/evidence/types/evidence.pb.go index 430f6cce694f..284f33a5ba0e 100644 --- a/x/evidence/types/evidence.pb.go +++ b/x/evidence/types/evidence.pb.go @@ -325,10 +325,7 @@ func (m *Equivocation) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthEvidence - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthEvidence } if (iNdEx + skippy) > l { diff --git a/x/evidence/types/genesis.pb.go b/x/evidence/types/genesis.pb.go index c40bb8a5290c..672a0ce8cf2e 100644 --- a/x/evidence/types/genesis.pb.go +++ b/x/evidence/types/genesis.pb.go @@ -232,10 +232,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { diff --git a/x/evidence/types/query.pb.go b/x/evidence/types/query.pb.go index c88579655d63..e084ea29c899 100644 --- a/x/evidence/types/query.pb.go +++ b/x/evidence/types/query.pb.go @@ -685,10 +685,7 @@ func (m *QueryEvidenceRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -774,10 +771,7 @@ func (m *QueryEvidenceResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -863,10 +857,7 @@ func (m *QueryAllEvidenceRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -986,10 +977,7 @@ func (m *QueryAllEvidenceResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { diff --git a/x/evidence/types/query.pb.gw.go b/x/evidence/types/query.pb.gw.go index e15d163524b4..5de488fd9c3f 100644 --- a/x/evidence/types/query.pb.gw.go +++ b/x/evidence/types/query.pb.gw.go @@ -13,7 +13,6 @@ import ( "io" "net/http" - "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -23,13 +22,11 @@ import ( "google.golang.org/grpc/status" ) -// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage func request_Query_Evidence_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryEvidenceRequest @@ -58,33 +55,6 @@ func request_Query_Evidence_0(ctx context.Context, marshaler runtime.Marshaler, } -func local_request_Query_Evidence_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryEvidenceRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["evidence_hash"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "evidence_hash") - } - - protoReq.EvidenceHash, err = runtime.Bytes(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "evidence_hash", err) - } - - msg, err := server.Evidence(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_AllEvidence_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -105,71 +75,6 @@ func request_Query_AllEvidence_0(ctx context.Context, marshaler runtime.Marshale } -func local_request_Query_AllEvidence_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryAllEvidenceRequest - 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_AllEvidence_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.AllEvidence(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". -// UnaryRPC :call QueryServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. -func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { - - mux.Handle("GET", pattern_Query_Evidence_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Evidence_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Evidence_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_AllEvidence_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_AllEvidence_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_AllEvidence_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/evidence/types/tx.pb.go b/x/evidence/types/tx.pb.go index d2a2f563e177..0cce8d2cbb4a 100644 --- a/x/evidence/types/tx.pb.go +++ b/x/evidence/types/tx.pb.go @@ -479,10 +479,7 @@ func (m *MsgSubmitEvidence) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -566,10 +563,7 @@ func (m *MsgSubmitEvidenceResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { diff --git a/x/genutil/types/genesis.pb.go b/x/genutil/types/genesis.pb.go index e9a9ebf9ae1e..369cd0edfaf6 100644 --- a/x/genutil/types/genesis.pb.go +++ b/x/genutil/types/genesis.pb.go @@ -228,10 +228,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { diff --git a/x/gov/types/genesis.pb.go b/x/gov/types/genesis.pb.go index 67022597280d..4df93da3d07b 100644 --- a/x/gov/types/genesis.pb.go +++ b/x/gov/types/genesis.pb.go @@ -568,10 +568,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { diff --git a/x/gov/types/gov.pb.go b/x/gov/types/gov.pb.go index 922186d01f0d..57730bcb9087 100644 --- a/x/gov/types/gov.pb.go +++ b/x/gov/types/gov.pb.go @@ -1355,10 +1355,7 @@ func (m *TextProposal) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGov - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGov } if (iNdEx + skippy) > l { @@ -1493,10 +1490,7 @@ func (m *Deposit) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGov - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGov } if (iNdEx + skippy) > l { @@ -1819,10 +1813,7 @@ func (m *Proposal) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGov - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGov } if (iNdEx + skippy) > l { @@ -2008,10 +1999,7 @@ func (m *TallyResult) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGov - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGov } if (iNdEx + skippy) > l { @@ -2131,10 +2119,7 @@ func (m *Vote) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGov - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGov } if (iNdEx + skippy) > l { @@ -2251,10 +2236,7 @@ func (m *DepositParams) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGov - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGov } if (iNdEx + skippy) > l { @@ -2337,10 +2319,7 @@ func (m *VotingParams) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGov - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGov } if (iNdEx + skippy) > l { @@ -2489,10 +2468,7 @@ func (m *TallyParams) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGov - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGov } if (iNdEx + skippy) > l { diff --git a/x/gov/types/query.pb.go b/x/gov/types/query.pb.go index 190cd901b3fa..4ca1f33ae5f4 100644 --- a/x/gov/types/query.pb.go +++ b/x/gov/types/query.pb.go @@ -2185,10 +2185,7 @@ func (m *QueryProposalRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2271,10 +2268,7 @@ func (m *QueryProposalResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2443,10 +2437,7 @@ func (m *QueryProposalsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2566,10 +2557,7 @@ func (m *QueryProposalsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2670,10 +2658,7 @@ func (m *QueryVoteRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2756,10 +2741,7 @@ func (m *QueryVoteResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2864,10 +2846,7 @@ func (m *QueryVotesRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2987,10 +2966,7 @@ func (m *QueryVotesResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3072,10 +3048,7 @@ func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3224,10 +3197,7 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3328,10 +3298,7 @@ func (m *QueryDepositRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3414,10 +3381,7 @@ func (m *QueryDepositResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3522,10 +3486,7 @@ func (m *QueryDepositsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3645,10 +3606,7 @@ func (m *QueryDepositsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3717,10 +3675,7 @@ func (m *QueryTallyResultRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3803,10 +3758,7 @@ func (m *QueryTallyResultResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { diff --git a/x/gov/types/query.pb.gw.go b/x/gov/types/query.pb.gw.go index 52814511b9cb..934b33f42d83 100644 --- a/x/gov/types/query.pb.gw.go +++ b/x/gov/types/query.pb.gw.go @@ -13,7 +13,6 @@ import ( "io" "net/http" - "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -23,13 +22,11 @@ import ( "google.golang.org/grpc/status" ) -// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage func request_Query_Proposal_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryProposalRequest @@ -58,33 +55,6 @@ func request_Query_Proposal_0(ctx context.Context, marshaler runtime.Marshaler, } -func local_request_Query_Proposal_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryProposalRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["proposal_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") - } - - protoReq.ProposalId, err = runtime.Uint64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) - } - - msg, err := server.Proposal(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_Proposals_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -105,22 +75,6 @@ func request_Query_Proposals_0(ctx context.Context, marshaler runtime.Marshaler, } -func local_request_Query_Proposals_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryProposalsRequest - 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_Proposals_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.Proposals(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_Vote_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryVoteRequest var metadata runtime.ServerMetadata @@ -159,44 +113,6 @@ func request_Query_Vote_0(ctx context.Context, marshaler runtime.Marshaler, clie } -func local_request_Query_Vote_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryVoteRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["proposal_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") - } - - protoReq.ProposalId, err = runtime.Uint64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) - } - - val, ok = pathParams["voter"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "voter") - } - - protoReq.Voter, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "voter", err) - } - - msg, err := server.Vote(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_Votes_0 = &utilities.DoubleArray{Encoding: map[string]int{"proposal_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -235,40 +151,6 @@ func request_Query_Votes_0(ctx context.Context, marshaler runtime.Marshaler, cli } -func local_request_Query_Votes_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryVotesRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["proposal_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") - } - - protoReq.ProposalId, err = runtime.Uint64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) - } - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Votes_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.Votes(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryParamsRequest var metadata runtime.ServerMetadata @@ -296,33 +178,6 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } -func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryParamsRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["params_type"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "params_type") - } - - protoReq.ParamsType, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "params_type", err) - } - - msg, err := server.Params(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_Deposit_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryDepositRequest var metadata runtime.ServerMetadata @@ -361,44 +216,6 @@ func request_Query_Deposit_0(ctx context.Context, marshaler runtime.Marshaler, c } -func local_request_Query_Deposit_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDepositRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["proposal_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") - } - - protoReq.ProposalId, err = runtime.Uint64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) - } - - val, ok = pathParams["depositor"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "depositor") - } - - protoReq.Depositor, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "depositor", err) - } - - msg, err := server.Deposit(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_Deposits_0 = &utilities.DoubleArray{Encoding: map[string]int{"proposal_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -437,40 +254,6 @@ func request_Query_Deposits_0(ctx context.Context, marshaler runtime.Marshaler, } -func local_request_Query_Deposits_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDepositsRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["proposal_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") - } - - protoReq.ProposalId, err = runtime.Uint64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) - } - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Deposits_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.Deposits(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_TallyResult_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryTallyResultRequest var metadata runtime.ServerMetadata @@ -498,202 +281,6 @@ func request_Query_TallyResult_0(ctx context.Context, marshaler runtime.Marshale } -func local_request_Query_TallyResult_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryTallyResultRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["proposal_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") - } - - protoReq.ProposalId, err = runtime.Uint64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) - } - - msg, err := server.TallyResult(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". -// UnaryRPC :call QueryServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. -func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { - - mux.Handle("GET", pattern_Query_Proposal_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Proposal_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Proposal_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Proposals_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Proposals_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Proposals_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Vote_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Vote_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Vote_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Votes_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Votes_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Votes_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Deposit_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Deposit_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Deposit_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Deposits_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Deposits_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Deposits_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_TallyResult_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_TallyResult_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_TallyResult_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/gov/types/tx.pb.go b/x/gov/types/tx.pb.go index c4d9a9670153..0261e1c13949 100644 --- a/x/gov/types/tx.pb.go +++ b/x/gov/types/tx.pb.go @@ -946,10 +946,7 @@ func (m *MsgSubmitProposal) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1018,10 +1015,7 @@ func (m *MsgSubmitProposalResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1141,10 +1135,7 @@ func (m *MsgVote) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1194,10 +1185,7 @@ func (m *MsgVoteResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1332,10 +1320,7 @@ func (m *MsgDeposit) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1385,10 +1370,7 @@ func (m *MsgDepositResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { diff --git a/x/ibc/applications/transfer/types/genesis.pb.go b/x/ibc/applications/transfer/types/genesis.pb.go index 7dc0370d8eaf..3ae0442f826b 100644 --- a/x/ibc/applications/transfer/types/genesis.pb.go +++ b/x/ibc/applications/transfer/types/genesis.pb.go @@ -342,10 +342,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { diff --git a/x/ibc/applications/transfer/types/query.pb.go b/x/ibc/applications/transfer/types/query.pb.go index ee069d35010e..1c1d69295192 100644 --- a/x/ibc/applications/transfer/types/query.pb.go +++ b/x/ibc/applications/transfer/types/query.pb.go @@ -889,10 +889,7 @@ func (m *QueryDenomTraceRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -978,10 +975,7 @@ func (m *QueryDenomTraceResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1067,10 +1061,7 @@ func (m *QueryDenomTracesRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1190,10 +1181,7 @@ func (m *QueryDenomTracesResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1243,10 +1231,7 @@ func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1332,10 +1317,7 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { diff --git a/x/ibc/applications/transfer/types/query.pb.gw.go b/x/ibc/applications/transfer/types/query.pb.gw.go index 99a7f1906350..92529fda662e 100644 --- a/x/ibc/applications/transfer/types/query.pb.gw.go +++ b/x/ibc/applications/transfer/types/query.pb.gw.go @@ -13,7 +13,6 @@ import ( "io" "net/http" - "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -23,13 +22,11 @@ import ( "google.golang.org/grpc/status" ) -// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage func request_Query_DenomTrace_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryDenomTraceRequest @@ -58,33 +55,6 @@ func request_Query_DenomTrace_0(ctx context.Context, marshaler runtime.Marshaler } -func local_request_Query_DenomTrace_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDenomTraceRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["hash"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "hash") - } - - protoReq.Hash, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "hash", err) - } - - msg, err := server.DenomTrace(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_DenomTraces_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -105,22 +75,6 @@ func request_Query_DenomTraces_0(ctx context.Context, marshaler runtime.Marshale } -func local_request_Query_DenomTraces_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDenomTracesRequest - 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_DenomTraces_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.DenomTraces(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryParamsRequest var metadata runtime.ServerMetadata @@ -130,84 +84,6 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } -func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryParamsRequest - var metadata runtime.ServerMetadata - - msg, err := server.Params(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". -// UnaryRPC :call QueryServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. -func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { - - mux.Handle("GET", pattern_Query_DenomTrace_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_DenomTrace_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_DenomTrace_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_DenomTraces_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_DenomTraces_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_DenomTraces_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/ibc/applications/transfer/types/transfer.pb.go b/x/ibc/applications/transfer/types/transfer.pb.go index c051db12a815..62734b85a49f 100644 --- a/x/ibc/applications/transfer/types/transfer.pb.go +++ b/x/ibc/applications/transfer/types/transfer.pb.go @@ -604,10 +604,7 @@ func (m *FungibleTokenPacketData) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTransfer - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTransfer } if (iNdEx + skippy) > l { @@ -721,10 +718,7 @@ func (m *DenomTrace) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTransfer - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTransfer } if (iNdEx + skippy) > l { @@ -814,10 +808,7 @@ func (m *Params) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTransfer - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTransfer } if (iNdEx + skippy) > l { diff --git a/x/ibc/applications/transfer/types/tx.pb.go b/x/ibc/applications/transfer/types/tx.pb.go index dd46dbe2610e..e3a630b42738 100644 --- a/x/ibc/applications/transfer/types/tx.pb.go +++ b/x/ibc/applications/transfer/types/tx.pb.go @@ -653,10 +653,7 @@ func (m *MsgTransfer) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -706,10 +703,7 @@ func (m *MsgTransferResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { diff --git a/x/ibc/core/02-client/types/client.pb.go b/x/ibc/core/02-client/types/client.pb.go index f6233435ca09..a42ddef4c593 100644 --- a/x/ibc/core/02-client/types/client.pb.go +++ b/x/ibc/core/02-client/types/client.pb.go @@ -861,10 +861,7 @@ func (m *IdentifiedClientState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthClient - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthClient } if (iNdEx + skippy) > l { @@ -983,10 +980,7 @@ func (m *ConsensusStateWithHeight) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthClient - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthClient } if (iNdEx + skippy) > l { @@ -1102,10 +1096,7 @@ func (m *ClientConsensusStates) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthClient - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthClient } if (iNdEx + skippy) > l { @@ -1287,10 +1278,7 @@ func (m *ClientUpdateProposal) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthClient - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthClient } if (iNdEx + skippy) > l { @@ -1378,10 +1366,7 @@ func (m *Height) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthClient - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthClient } if (iNdEx + skippy) > l { @@ -1463,10 +1448,7 @@ func (m *Params) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthClient - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthClient } if (iNdEx + skippy) > l { diff --git a/x/ibc/core/02-client/types/genesis.pb.go b/x/ibc/core/02-client/types/genesis.pb.go index 07f996ac203d..a8253c343db0 100644 --- a/x/ibc/core/02-client/types/genesis.pb.go +++ b/x/ibc/core/02-client/types/genesis.pb.go @@ -722,10 +722,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { @@ -843,10 +840,7 @@ func (m *GenesisMetadata) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { @@ -962,10 +956,7 @@ func (m *IdentifiedGenesisMetadata) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { diff --git a/x/ibc/core/02-client/types/query.pb.go b/x/ibc/core/02-client/types/query.pb.go index afe6670d4b67..651becb899ae 100644 --- a/x/ibc/core/02-client/types/query.pb.go +++ b/x/ibc/core/02-client/types/query.pb.go @@ -1556,10 +1556,7 @@ func (m *QueryClientStateRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1712,10 +1709,7 @@ func (m *QueryClientStateResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1801,10 +1795,7 @@ func (m *QueryClientStatesRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1924,10 +1915,7 @@ func (m *QueryClientStatesResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2067,10 +2055,7 @@ func (m *QueryConsensusStateRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2223,10 +2208,7 @@ func (m *QueryConsensusStateResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2344,10 +2326,7 @@ func (m *QueryConsensusStatesRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2467,10 +2446,7 @@ func (m *QueryConsensusStatesResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2520,10 +2496,7 @@ func (m *QueryClientParamsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2609,10 +2582,7 @@ func (m *QueryClientParamsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { diff --git a/x/ibc/core/02-client/types/query.pb.gw.go b/x/ibc/core/02-client/types/query.pb.gw.go index d4414d5ea33b..529a7b2f3f96 100644 --- a/x/ibc/core/02-client/types/query.pb.gw.go +++ b/x/ibc/core/02-client/types/query.pb.gw.go @@ -13,7 +13,6 @@ import ( "io" "net/http" - "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -23,13 +22,11 @@ import ( "google.golang.org/grpc/status" ) -// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage func request_Query_ClientState_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryClientStateRequest @@ -58,33 +55,6 @@ func request_Query_ClientState_0(ctx context.Context, marshaler runtime.Marshale } -func local_request_Query_ClientState_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryClientStateRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["client_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "client_id") - } - - protoReq.ClientId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "client_id", err) - } - - msg, err := server.ClientState(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_ClientStates_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -105,22 +75,6 @@ func request_Query_ClientStates_0(ctx context.Context, marshaler runtime.Marshal } -func local_request_Query_ClientStates_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryClientStatesRequest - 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_ClientStates_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ClientStates(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_ConsensusState_0 = &utilities.DoubleArray{Encoding: map[string]int{"client_id": 0, "revision_number": 1, "revision_height": 2}, Base: []int{1, 1, 2, 3, 0, 0, 0}, Check: []int{0, 1, 1, 1, 2, 3, 4}} ) @@ -181,62 +135,6 @@ func request_Query_ConsensusState_0(ctx context.Context, marshaler runtime.Marsh } -func local_request_Query_ConsensusState_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryConsensusStateRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["client_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "client_id") - } - - protoReq.ClientId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "client_id", err) - } - - val, ok = pathParams["revision_number"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "revision_number") - } - - protoReq.RevisionNumber, err = runtime.Uint64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "revision_number", err) - } - - val, ok = pathParams["revision_height"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "revision_height") - } - - protoReq.RevisionHeight, err = runtime.Uint64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "revision_height", err) - } - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ConsensusState_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ConsensusState(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_ConsensusStates_0 = &utilities.DoubleArray{Encoding: map[string]int{"client_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -275,40 +173,6 @@ func request_Query_ConsensusStates_0(ctx context.Context, marshaler runtime.Mars } -func local_request_Query_ConsensusStates_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryConsensusStatesRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["client_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "client_id") - } - - protoReq.ClientId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "client_id", err) - } - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ConsensusStates_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ConsensusStates(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_ClientParams_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryClientParamsRequest var metadata runtime.ServerMetadata @@ -318,124 +182,6 @@ func request_Query_ClientParams_0(ctx context.Context, marshaler runtime.Marshal } -func local_request_Query_ClientParams_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryClientParamsRequest - var metadata runtime.ServerMetadata - - msg, err := server.ClientParams(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". -// UnaryRPC :call QueryServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. -func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { - - mux.Handle("GET", pattern_Query_ClientState_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_ClientState_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ClientState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_ClientStates_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_ClientStates_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ClientStates_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_ConsensusState_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_ConsensusState_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ConsensusState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_ConsensusStates_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_ConsensusStates_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ConsensusStates_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_ClientParams_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_ClientParams_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ClientParams_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/ibc/core/02-client/types/tx.pb.go b/x/ibc/core/02-client/types/tx.pb.go index b0bf22d0cc11..a314223fcff9 100644 --- a/x/ibc/core/02-client/types/tx.pb.go +++ b/x/ibc/core/02-client/types/tx.pb.go @@ -1216,10 +1216,7 @@ func (m *MsgCreateClient) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1269,10 +1266,7 @@ func (m *MsgCreateClientResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1422,10 +1416,7 @@ func (m *MsgUpdateClient) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1475,10 +1466,7 @@ func (m *MsgUpdateClientResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1732,10 +1720,7 @@ func (m *MsgUpgradeClient) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1785,10 +1770,7 @@ func (m *MsgUpgradeClientResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1938,10 +1920,7 @@ func (m *MsgSubmitMisbehaviour) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1991,10 +1970,7 @@ func (m *MsgSubmitMisbehaviourResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { diff --git a/x/ibc/core/03-connection/types/connection.pb.go b/x/ibc/core/03-connection/types/connection.pb.go index cdfb752b9075..14b85c62d432 100644 --- a/x/ibc/core/03-connection/types/connection.pb.go +++ b/x/ibc/core/03-connection/types/connection.pb.go @@ -1023,10 +1023,7 @@ func (m *ConnectionEnd) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthConnection - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthConnection } if (iNdEx + skippy) > l { @@ -1245,10 +1242,7 @@ func (m *IdentifiedConnection) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthConnection - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthConnection } if (iNdEx + skippy) > l { @@ -1395,10 +1389,7 @@ func (m *Counterparty) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthConnection - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthConnection } if (iNdEx + skippy) > l { @@ -1480,10 +1471,7 @@ func (m *ClientPaths) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthConnection - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthConnection } if (iNdEx + skippy) > l { @@ -1597,10 +1585,7 @@ func (m *ConnectionPaths) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthConnection - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthConnection } if (iNdEx + skippy) > l { @@ -1714,10 +1699,7 @@ func (m *Version) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthConnection - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthConnection } if (iNdEx + skippy) > l { diff --git a/x/ibc/core/03-connection/types/genesis.pb.go b/x/ibc/core/03-connection/types/genesis.pb.go index 19c4e6aeb823..5f33f166ae07 100644 --- a/x/ibc/core/03-connection/types/genesis.pb.go +++ b/x/ibc/core/03-connection/types/genesis.pb.go @@ -337,10 +337,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { diff --git a/x/ibc/core/03-connection/types/query.pb.go b/x/ibc/core/03-connection/types/query.pb.go index 2861c8a5fbcc..6796cdb1f8ad 100644 --- a/x/ibc/core/03-connection/types/query.pb.go +++ b/x/ibc/core/03-connection/types/query.pb.go @@ -1628,10 +1628,7 @@ func (m *QueryConnectionRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1784,10 +1781,7 @@ func (m *QueryConnectionResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1873,10 +1867,7 @@ func (m *QueryConnectionsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2029,10 +2020,7 @@ func (m *QueryConnectionsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2114,10 +2102,7 @@ func (m *QueryClientConnectionsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2266,10 +2251,7 @@ func (m *QueryClientConnectionsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2351,10 +2333,7 @@ func (m *QueryConnectionClientStateRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2507,10 +2486,7 @@ func (m *QueryConnectionClientStateResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2630,10 +2606,7 @@ func (m *QueryConnectionConsensusStateRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -2818,10 +2791,7 @@ func (m *QueryConnectionConsensusStateResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { diff --git a/x/ibc/core/03-connection/types/query.pb.gw.go b/x/ibc/core/03-connection/types/query.pb.gw.go index 3e6de4e06415..95a65726b8b8 100644 --- a/x/ibc/core/03-connection/types/query.pb.gw.go +++ b/x/ibc/core/03-connection/types/query.pb.gw.go @@ -13,7 +13,6 @@ import ( "io" "net/http" - "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -23,13 +22,11 @@ import ( "google.golang.org/grpc/status" ) -// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage func request_Query_Connection_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryConnectionRequest @@ -58,33 +55,6 @@ func request_Query_Connection_0(ctx context.Context, marshaler runtime.Marshaler } -func local_request_Query_Connection_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryConnectionRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["connection_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "connection_id") - } - - protoReq.ConnectionId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "connection_id", err) - } - - msg, err := server.Connection(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_Connections_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -105,22 +75,6 @@ func request_Query_Connections_0(ctx context.Context, marshaler runtime.Marshale } -func local_request_Query_Connections_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryConnectionsRequest - 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_Connections_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.Connections(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_ClientConnections_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryClientConnectionsRequest var metadata runtime.ServerMetadata @@ -148,33 +102,6 @@ func request_Query_ClientConnections_0(ctx context.Context, marshaler runtime.Ma } -func local_request_Query_ClientConnections_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryClientConnectionsRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["client_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "client_id") - } - - protoReq.ClientId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "client_id", err) - } - - msg, err := server.ClientConnections(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_ConnectionClientState_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryConnectionClientStateRequest var metadata runtime.ServerMetadata @@ -202,33 +129,6 @@ func request_Query_ConnectionClientState_0(ctx context.Context, marshaler runtim } -func local_request_Query_ConnectionClientState_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryConnectionClientStateRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["connection_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "connection_id") - } - - protoReq.ConnectionId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "connection_id", err) - } - - msg, err := server.ConnectionClientState(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_ConnectionConsensusState_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryConnectionConsensusStateRequest var metadata runtime.ServerMetadata @@ -278,164 +178,6 @@ func request_Query_ConnectionConsensusState_0(ctx context.Context, marshaler run } -func local_request_Query_ConnectionConsensusState_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryConnectionConsensusStateRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["connection_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "connection_id") - } - - protoReq.ConnectionId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "connection_id", err) - } - - val, ok = pathParams["revision_number"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "revision_number") - } - - protoReq.RevisionNumber, err = runtime.Uint64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "revision_number", err) - } - - val, ok = pathParams["revision_height"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "revision_height") - } - - protoReq.RevisionHeight, err = runtime.Uint64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "revision_height", err) - } - - msg, err := server.ConnectionConsensusState(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". -// UnaryRPC :call QueryServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. -func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { - - mux.Handle("GET", pattern_Query_Connection_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Connection_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Connection_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Connections_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Connections_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Connections_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_ClientConnections_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_ClientConnections_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ClientConnections_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_ConnectionClientState_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_ConnectionClientState_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ConnectionClientState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_ConnectionConsensusState_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_ConnectionConsensusState_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ConnectionConsensusState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/ibc/core/03-connection/types/tx.pb.go b/x/ibc/core/03-connection/types/tx.pb.go index 5b1ce774649b..00e4fd9d0bb7 100644 --- a/x/ibc/core/03-connection/types/tx.pb.go +++ b/x/ibc/core/03-connection/types/tx.pb.go @@ -1474,10 +1474,7 @@ func (m *MsgConnectionOpenInit) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1527,10 +1524,7 @@ func (m *MsgConnectionOpenInitResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1966,10 +1960,7 @@ func (m *MsgConnectionOpenTry) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2019,10 +2010,7 @@ func (m *MsgConnectionOpenTryResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2408,10 +2396,7 @@ func (m *MsgConnectionOpenAck) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2461,10 +2446,7 @@ func (m *MsgConnectionOpenAckResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2645,10 +2627,7 @@ func (m *MsgConnectionOpenConfirm) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2698,10 +2677,7 @@ func (m *MsgConnectionOpenConfirmResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { diff --git a/x/ibc/core/04-channel/types/channel.pb.go b/x/ibc/core/04-channel/types/channel.pb.go index e1be136186e6..1384a150d578 100644 --- a/x/ibc/core/04-channel/types/channel.pb.go +++ b/x/ibc/core/04-channel/types/channel.pb.go @@ -1239,10 +1239,7 @@ func (m *Channel) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthChannel - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthChannel } if (iNdEx + skippy) > l { @@ -1491,10 +1488,7 @@ func (m *IdentifiedChannel) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthChannel - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthChannel } if (iNdEx + skippy) > l { @@ -1608,10 +1602,7 @@ func (m *Counterparty) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthChannel - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthChannel } if (iNdEx + skippy) > l { @@ -1894,10 +1885,7 @@ func (m *Packet) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthChannel - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthChannel } if (iNdEx + skippy) > l { @@ -2064,10 +2052,7 @@ func (m *PacketState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthChannel - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthChannel } if (iNdEx + skippy) > l { @@ -2182,10 +2167,7 @@ func (m *Acknowledgement) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthChannel - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthChannel } if (iNdEx + skippy) > l { diff --git a/x/ibc/core/04-channel/types/genesis.pb.go b/x/ibc/core/04-channel/types/genesis.pb.go index 51ff4e50771c..c54c6f9deb03 100644 --- a/x/ibc/core/04-channel/types/genesis.pb.go +++ b/x/ibc/core/04-channel/types/genesis.pb.go @@ -781,10 +781,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { @@ -917,10 +914,7 @@ func (m *PacketSequence) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { diff --git a/x/ibc/core/04-channel/types/query.pb.go b/x/ibc/core/04-channel/types/query.pb.go index d163f3d8ce62..c5cbd6e8f899 100644 --- a/x/ibc/core/04-channel/types/query.pb.go +++ b/x/ibc/core/04-channel/types/query.pb.go @@ -4231,10 +4231,7 @@ func (m *QueryChannelRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -4387,10 +4384,7 @@ func (m *QueryChannelResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -4476,10 +4470,7 @@ func (m *QueryChannelsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -4632,10 +4623,7 @@ func (m *QueryChannelsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -4753,10 +4741,7 @@ func (m *QueryConnectionChannelsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -4909,10 +4894,7 @@ func (m *QueryConnectionChannelsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -5026,10 +5008,7 @@ func (m *QueryChannelClientStateRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -5182,10 +5161,7 @@ func (m *QueryChannelClientStateResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -5337,10 +5313,7 @@ func (m *QueryChannelConsensusStateRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -5525,10 +5498,7 @@ func (m *QueryChannelConsensusStateResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -5661,10 +5631,7 @@ func (m *QueryPacketCommitmentRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -5815,10 +5782,7 @@ func (m *QueryPacketCommitmentResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -5968,10 +5932,7 @@ func (m *QueryPacketCommitmentsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -6124,10 +6085,7 @@ func (m *QueryPacketCommitmentsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -6260,10 +6218,7 @@ func (m *QueryPacketReceiptRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -6400,10 +6355,7 @@ func (m *QueryPacketReceiptResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -6536,10 +6488,7 @@ func (m *QueryPacketAcknowledgementRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -6690,10 +6639,7 @@ func (m *QueryPacketAcknowledgementResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -6843,10 +6789,7 @@ func (m *QueryPacketAcknowledgementsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -6999,10 +6942,7 @@ func (m *QueryPacketAcknowledgementsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -7192,10 +7132,7 @@ func (m *QueryUnreceivedPacketsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -7354,10 +7291,7 @@ func (m *QueryUnreceivedPacketsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -7547,10 +7481,7 @@ func (m *QueryUnreceivedAcksRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -7709,10 +7640,7 @@ func (m *QueryUnreceivedAcksResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -7826,10 +7754,7 @@ func (m *QueryNextSequenceReceiveRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -7965,10 +7890,7 @@ func (m *QueryNextSequenceReceiveResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { diff --git a/x/ibc/core/04-channel/types/query.pb.gw.go b/x/ibc/core/04-channel/types/query.pb.gw.go index bb5a94aba749..4fe5bd4399fa 100644 --- a/x/ibc/core/04-channel/types/query.pb.gw.go +++ b/x/ibc/core/04-channel/types/query.pb.gw.go @@ -13,7 +13,6 @@ import ( "io" "net/http" - "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -23,13 +22,11 @@ import ( "google.golang.org/grpc/status" ) -// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage func request_Query_Channel_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryChannelRequest @@ -69,44 +66,6 @@ func request_Query_Channel_0(ctx context.Context, marshaler runtime.Marshaler, c } -func local_request_Query_Channel_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryChannelRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["channel_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") - } - - protoReq.ChannelId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) - } - - val, ok = pathParams["port_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") - } - - protoReq.PortId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) - } - - msg, err := server.Channel(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_Channels_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -127,22 +86,6 @@ func request_Query_Channels_0(ctx context.Context, marshaler runtime.Marshaler, } -func local_request_Query_Channels_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryChannelsRequest - 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_Channels_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.Channels(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_ConnectionChannels_0 = &utilities.DoubleArray{Encoding: map[string]int{"connection": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -181,40 +124,6 @@ func request_Query_ConnectionChannels_0(ctx context.Context, marshaler runtime.M } -func local_request_Query_ConnectionChannels_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryConnectionChannelsRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["connection"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "connection") - } - - protoReq.Connection, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "connection", err) - } - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ConnectionChannels_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ConnectionChannels(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_ChannelClientState_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryChannelClientStateRequest var metadata runtime.ServerMetadata @@ -253,44 +162,6 @@ func request_Query_ChannelClientState_0(ctx context.Context, marshaler runtime.M } -func local_request_Query_ChannelClientState_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryChannelClientStateRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["channel_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") - } - - protoReq.ChannelId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) - } - - val, ok = pathParams["port_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") - } - - protoReq.PortId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) - } - - msg, err := server.ChannelClientState(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_ChannelConsensusState_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryChannelConsensusStateRequest var metadata runtime.ServerMetadata @@ -351,8 +222,8 @@ func request_Query_ChannelConsensusState_0(ctx context.Context, marshaler runtim } -func local_request_Query_ChannelConsensusState_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryChannelConsensusStateRequest +func request_Query_PacketCommitment_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPacketCommitmentRequest var metadata runtime.ServerMetadata var ( @@ -384,35 +255,28 @@ func local_request_Query_ChannelConsensusState_0(ctx context.Context, marshaler return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) } - val, ok = pathParams["revision_number"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "revision_number") - } - - protoReq.RevisionNumber, err = runtime.Uint64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "revision_number", err) - } - - val, ok = pathParams["revision_height"] + val, ok = pathParams["sequence"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "revision_height") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sequence") } - protoReq.RevisionHeight, err = runtime.Uint64(val) + protoReq.Sequence, err = runtime.Uint64(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "revision_height", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sequence", err) } - msg, err := server.ChannelConsensusState(ctx, &protoReq) + msg, err := client.PacketCommitment(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func request_Query_PacketCommitment_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPacketCommitmentRequest +var ( + filter_Query_PacketCommitments_0 = &utilities.DoubleArray{Encoding: map[string]int{"channel_id": 0, "port_id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} +) + +func request_Query_PacketCommitments_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPacketCommitmentsRequest var metadata runtime.ServerMetadata var ( @@ -444,24 +308,20 @@ func request_Query_PacketCommitment_0(ctx context.Context, marshaler runtime.Mar return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) } - val, ok = pathParams["sequence"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sequence") + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - - protoReq.Sequence, err = runtime.Uint64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sequence", err) + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_PacketCommitments_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.PacketCommitment(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.PacketCommitments(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func local_request_Query_PacketCommitment_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPacketCommitmentRequest +func request_Query_PacketReceipt_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPacketReceiptRequest var metadata runtime.ServerMetadata var ( @@ -504,17 +364,13 @@ func local_request_Query_PacketCommitment_0(ctx context.Context, marshaler runti return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sequence", err) } - msg, err := server.PacketCommitment(ctx, &protoReq) + msg, err := client.PacketReceipt(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -var ( - filter_Query_PacketCommitments_0 = &utilities.DoubleArray{Encoding: map[string]int{"channel_id": 0, "port_id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} -) - -func request_Query_PacketCommitments_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPacketCommitmentsRequest +func request_Query_PacketAcknowledgement_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPacketAcknowledgementRequest var metadata runtime.ServerMetadata var ( @@ -546,20 +402,28 @@ func request_Query_PacketCommitments_0(ctx context.Context, marshaler runtime.Ma return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) } - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + val, ok = pathParams["sequence"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sequence") } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_PacketCommitments_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + + protoReq.Sequence, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sequence", err) } - msg, err := client.PacketCommitments(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.PacketAcknowledgement(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func local_request_Query_PacketCommitments_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPacketCommitmentsRequest +var ( + filter_Query_PacketAcknowledgements_0 = &utilities.DoubleArray{Encoding: map[string]int{"channel_id": 0, "port_id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} +) + +func request_Query_PacketAcknowledgements_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPacketAcknowledgementsRequest var metadata runtime.ServerMetadata var ( @@ -594,17 +458,17 @@ func local_request_Query_PacketCommitments_0(ctx context.Context, marshaler runt if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_PacketCommitments_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_PacketAcknowledgements_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.PacketCommitments(ctx, &protoReq) + msg, err := client.PacketAcknowledgements(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func request_Query_PacketReceipt_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPacketReceiptRequest +func request_Query_UnreceivedPackets_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUnreceivedPacketsRequest var metadata runtime.ServerMetadata var ( @@ -636,24 +500,24 @@ func request_Query_PacketReceipt_0(ctx context.Context, marshaler runtime.Marsha return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) } - val, ok = pathParams["sequence"] + val, ok = pathParams["packet_commitment_sequences"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sequence") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_commitment_sequences") } - protoReq.Sequence, err = runtime.Uint64(val) + protoReq.PacketCommitmentSequences, err = runtime.Uint64Slice(val, ",") if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sequence", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_commitment_sequences", err) } - msg, err := client.PacketReceipt(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.UnreceivedPackets(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func local_request_Query_PacketReceipt_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPacketReceiptRequest +func request_Query_UnreceivedAcks_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUnreceivedAcksRequest var metadata runtime.ServerMetadata var ( @@ -685,24 +549,24 @@ func local_request_Query_PacketReceipt_0(ctx context.Context, marshaler runtime. return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) } - val, ok = pathParams["sequence"] + val, ok = pathParams["packet_ack_sequences"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sequence") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_ack_sequences") } - protoReq.Sequence, err = runtime.Uint64(val) + protoReq.PacketAckSequences, err = runtime.Uint64Slice(val, ",") if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sequence", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_ack_sequences", err) } - msg, err := server.PacketReceipt(ctx, &protoReq) + msg, err := client.UnreceivedAcks(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func request_Query_PacketAcknowledgement_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPacketAcknowledgementRequest +func request_Query_NextSequenceReceive_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryNextSequenceReceiveRequest var metadata runtime.ServerMetadata var ( @@ -734,706 +598,11 @@ func request_Query_PacketAcknowledgement_0(ctx context.Context, marshaler runtim return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) } - val, ok = pathParams["sequence"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sequence") - } - - protoReq.Sequence, err = runtime.Uint64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sequence", err) - } - - msg, err := client.PacketAcknowledgement(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.NextSequenceReceive(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func local_request_Query_PacketAcknowledgement_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPacketAcknowledgementRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["channel_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") - } - - protoReq.ChannelId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) - } - - val, ok = pathParams["port_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") - } - - protoReq.PortId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) - } - - val, ok = pathParams["sequence"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sequence") - } - - protoReq.Sequence, err = runtime.Uint64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sequence", err) - } - - msg, err := server.PacketAcknowledgement(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_Query_PacketAcknowledgements_0 = &utilities.DoubleArray{Encoding: map[string]int{"channel_id": 0, "port_id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} -) - -func request_Query_PacketAcknowledgements_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPacketAcknowledgementsRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["channel_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") - } - - protoReq.ChannelId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) - } - - val, ok = pathParams["port_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") - } - - protoReq.PortId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) - } - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_PacketAcknowledgements_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.PacketAcknowledgements(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Query_PacketAcknowledgements_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPacketAcknowledgementsRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["channel_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") - } - - protoReq.ChannelId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) - } - - val, ok = pathParams["port_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") - } - - protoReq.PortId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) - } - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_PacketAcknowledgements_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.PacketAcknowledgements(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Query_UnreceivedPackets_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryUnreceivedPacketsRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["channel_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") - } - - protoReq.ChannelId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) - } - - val, ok = pathParams["port_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") - } - - protoReq.PortId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) - } - - val, ok = pathParams["packet_commitment_sequences"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_commitment_sequences") - } - - protoReq.PacketCommitmentSequences, err = runtime.Uint64Slice(val, ",") - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_commitment_sequences", err) - } - - msg, err := client.UnreceivedPackets(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Query_UnreceivedPackets_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryUnreceivedPacketsRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["channel_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") - } - - protoReq.ChannelId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) - } - - val, ok = pathParams["port_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") - } - - protoReq.PortId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) - } - - val, ok = pathParams["packet_commitment_sequences"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_commitment_sequences") - } - - protoReq.PacketCommitmentSequences, err = runtime.Uint64Slice(val, ",") - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_commitment_sequences", err) - } - - msg, err := server.UnreceivedPackets(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Query_UnreceivedAcks_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryUnreceivedAcksRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["channel_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") - } - - protoReq.ChannelId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) - } - - val, ok = pathParams["port_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") - } - - protoReq.PortId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) - } - - val, ok = pathParams["packet_ack_sequences"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_ack_sequences") - } - - protoReq.PacketAckSequences, err = runtime.Uint64Slice(val, ",") - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_ack_sequences", err) - } - - msg, err := client.UnreceivedAcks(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Query_UnreceivedAcks_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryUnreceivedAcksRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["channel_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") - } - - protoReq.ChannelId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) - } - - val, ok = pathParams["port_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") - } - - protoReq.PortId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) - } - - val, ok = pathParams["packet_ack_sequences"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_ack_sequences") - } - - protoReq.PacketAckSequences, err = runtime.Uint64Slice(val, ",") - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_ack_sequences", err) - } - - msg, err := server.UnreceivedAcks(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Query_NextSequenceReceive_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryNextSequenceReceiveRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["channel_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") - } - - protoReq.ChannelId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) - } - - val, ok = pathParams["port_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") - } - - protoReq.PortId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) - } - - msg, err := client.NextSequenceReceive(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Query_NextSequenceReceive_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryNextSequenceReceiveRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["channel_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") - } - - protoReq.ChannelId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) - } - - val, ok = pathParams["port_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") - } - - protoReq.PortId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) - } - - msg, err := server.NextSequenceReceive(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". -// UnaryRPC :call QueryServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. -func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { - - mux.Handle("GET", pattern_Query_Channel_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Channel_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Channel_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Channels_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Channels_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Channels_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_ConnectionChannels_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_ConnectionChannels_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ConnectionChannels_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_ChannelClientState_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_ChannelClientState_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ChannelClientState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_ChannelConsensusState_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_ChannelConsensusState_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ChannelConsensusState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_PacketCommitment_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_PacketCommitment_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_PacketCommitment_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_PacketCommitments_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_PacketCommitments_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_PacketCommitments_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_PacketReceipt_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_PacketReceipt_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_PacketReceipt_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_PacketAcknowledgement_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_PacketAcknowledgement_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_PacketAcknowledgement_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_PacketAcknowledgements_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_PacketAcknowledgements_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_PacketAcknowledgements_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_UnreceivedPackets_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_UnreceivedPackets_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_UnreceivedPackets_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_UnreceivedAcks_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_UnreceivedAcks_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_UnreceivedAcks_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_NextSequenceReceive_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_NextSequenceReceive_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_NextSequenceReceive_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/ibc/core/04-channel/types/tx.pb.go b/x/ibc/core/04-channel/types/tx.pb.go index 9d2f3e221e98..df6a9653f671 100644 --- a/x/ibc/core/04-channel/types/tx.pb.go +++ b/x/ibc/core/04-channel/types/tx.pb.go @@ -2697,10 +2697,7 @@ func (m *MsgChannelOpenInit) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2750,10 +2747,7 @@ func (m *MsgChannelOpenInitResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -3031,10 +3025,7 @@ func (m *MsgChannelOpenTry) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -3084,10 +3075,7 @@ func (m *MsgChannelOpenTryResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -3364,10 +3352,7 @@ func (m *MsgChannelOpenAck) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -3417,10 +3402,7 @@ func (m *MsgChannelOpenAckResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -3633,10 +3615,7 @@ func (m *MsgChannelOpenConfirm) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -3686,10 +3665,7 @@ func (m *MsgChannelOpenConfirmResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -3835,10 +3811,7 @@ func (m *MsgChannelCloseInit) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -3888,10 +3861,7 @@ func (m *MsgChannelCloseInitResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -4104,10 +4074,7 @@ func (m *MsgChannelCloseConfirm) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -4157,10 +4124,7 @@ func (m *MsgChannelCloseConfirmResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -4342,10 +4306,7 @@ func (m *MsgRecvPacket) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -4395,10 +4356,7 @@ func (m *MsgRecvPacketResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -4599,10 +4557,7 @@ func (m *MsgTimeout) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -4652,10 +4607,7 @@ func (m *MsgTimeoutResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -4890,10 +4842,7 @@ func (m *MsgTimeoutOnClose) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -4943,10 +4892,7 @@ func (m *MsgTimeoutOnCloseResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -5162,10 +5108,7 @@ func (m *MsgAcknowledgement) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -5215,10 +5158,7 @@ func (m *MsgAcknowledgementResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { diff --git a/x/ibc/core/23-commitment/types/commitment.pb.go b/x/ibc/core/23-commitment/types/commitment.pb.go index 9634e25735c9..06bc66522611 100644 --- a/x/ibc/core/23-commitment/types/commitment.pb.go +++ b/x/ibc/core/23-commitment/types/commitment.pb.go @@ -512,10 +512,7 @@ func (m *MerkleRoot) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthCommitment - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthCommitment } if (iNdEx + skippy) > l { @@ -599,10 +596,7 @@ func (m *MerklePrefix) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthCommitment - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthCommitment } if (iNdEx + skippy) > l { @@ -684,10 +678,7 @@ func (m *MerklePath) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthCommitment - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthCommitment } if (iNdEx + skippy) > l { @@ -771,10 +762,7 @@ func (m *MerkleProof) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthCommitment - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthCommitment } if (iNdEx + skippy) > l { diff --git a/x/ibc/core/types/genesis.pb.go b/x/ibc/core/types/genesis.pb.go index aed5541827ff..a6f2b1754052 100644 --- a/x/ibc/core/types/genesis.pb.go +++ b/x/ibc/core/types/genesis.pb.go @@ -339,10 +339,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { diff --git a/x/ibc/light-clients/06-solomachine/types/solomachine.pb.go b/x/ibc/light-clients/06-solomachine/types/solomachine.pb.go index 592d73b22b4e..8b31fb0d4116 100644 --- a/x/ibc/light-clients/06-solomachine/types/solomachine.pb.go +++ b/x/ibc/light-clients/06-solomachine/types/solomachine.pb.go @@ -2064,10 +2064,7 @@ func (m *ClientState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSolomachine } if (iNdEx + skippy) > l { @@ -2204,10 +2201,7 @@ func (m *ConsensusState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSolomachine } if (iNdEx + skippy) > l { @@ -2397,10 +2391,7 @@ func (m *Header) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSolomachine } if (iNdEx + skippy) > l { @@ -2573,10 +2564,7 @@ func (m *Misbehaviour) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSolomachine } if (iNdEx + skippy) > l { @@ -2732,10 +2720,7 @@ func (m *SignatureAndData) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSolomachine } if (iNdEx + skippy) > l { @@ -2838,10 +2823,7 @@ func (m *TimestampedSignatureData) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSolomachine } if (iNdEx + skippy) > l { @@ -3014,10 +2996,7 @@ func (m *SignBytes) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSolomachine } if (iNdEx + skippy) > l { @@ -3135,10 +3114,7 @@ func (m *HeaderData) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSolomachine } if (iNdEx + skippy) > l { @@ -3258,10 +3234,7 @@ func (m *ClientStateData) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSolomachine } if (iNdEx + skippy) > l { @@ -3381,10 +3354,7 @@ func (m *ConsensusStateData) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSolomachine } if (iNdEx + skippy) > l { @@ -3504,10 +3474,7 @@ func (m *ConnectionStateData) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSolomachine } if (iNdEx + skippy) > l { @@ -3627,10 +3594,7 @@ func (m *ChannelStateData) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSolomachine } if (iNdEx + skippy) > l { @@ -3748,10 +3712,7 @@ func (m *PacketCommitmentData) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSolomachine } if (iNdEx + skippy) > l { @@ -3869,10 +3830,7 @@ func (m *PacketAcknowledgementData) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSolomachine } if (iNdEx + skippy) > l { @@ -3956,10 +3914,7 @@ func (m *PacketReceiptAbsenceData) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSolomachine } if (iNdEx + skippy) > l { @@ -4062,10 +4017,7 @@ func (m *NextSequenceRecvData) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSolomachine } if (iNdEx + skippy) > l { diff --git a/x/ibc/light-clients/07-tendermint/types/tendermint.pb.go b/x/ibc/light-clients/07-tendermint/types/tendermint.pb.go index 9993ed261db0..510a643c256b 100644 --- a/x/ibc/light-clients/07-tendermint/types/tendermint.pb.go +++ b/x/ibc/light-clients/07-tendermint/types/tendermint.pb.go @@ -1230,10 +1230,7 @@ func (m *ClientState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTendermint - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTendermint } if (iNdEx + skippy) > l { @@ -1383,10 +1380,7 @@ func (m *ConsensusState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTendermint - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTendermint } if (iNdEx + skippy) > l { @@ -1540,10 +1534,7 @@ func (m *Misbehaviour) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTendermint - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTendermint } if (iNdEx + skippy) > l { @@ -1734,10 +1725,7 @@ func (m *Header) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTendermint - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTendermint } if (iNdEx + skippy) > l { @@ -1825,10 +1813,7 @@ func (m *Fraction) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTendermint - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTendermint } if (iNdEx + skippy) > l { diff --git a/x/ibc/light-clients/09-localhost/types/localhost.pb.go b/x/ibc/light-clients/09-localhost/types/localhost.pb.go index 28f7f74d3879..53f01758492b 100644 --- a/x/ibc/light-clients/09-localhost/types/localhost.pb.go +++ b/x/ibc/light-clients/09-localhost/types/localhost.pb.go @@ -268,10 +268,7 @@ func (m *ClientState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthLocalhost - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthLocalhost } if (iNdEx + skippy) > l { diff --git a/x/mint/types/genesis.pb.go b/x/mint/types/genesis.pb.go index d764cfcf46f5..1486c35f2232 100644 --- a/x/mint/types/genesis.pb.go +++ b/x/mint/types/genesis.pb.go @@ -276,10 +276,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { diff --git a/x/mint/types/mint.pb.go b/x/mint/types/mint.pb.go index 2575c2f96fbe..4ed1cccd6978 100644 --- a/x/mint/types/mint.pb.go +++ b/x/mint/types/mint.pb.go @@ -441,10 +441,7 @@ func (m *Minter) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthMint - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthMint } if (iNdEx + skippy) > l { @@ -681,10 +678,7 @@ func (m *Params) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthMint - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthMint } if (iNdEx + skippy) > l { diff --git a/x/mint/types/query.pb.go b/x/mint/types/query.pb.go index ea5f843cd0e3..f707eb810d2d 100644 --- a/x/mint/types/query.pb.go +++ b/x/mint/types/query.pb.go @@ -749,10 +749,7 @@ func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -835,10 +832,7 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -888,10 +882,7 @@ func (m *QueryInflationRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -974,10 +965,7 @@ func (m *QueryInflationResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1027,10 +1015,7 @@ func (m *QueryAnnualProvisionsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1113,10 +1098,7 @@ func (m *QueryAnnualProvisionsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { diff --git a/x/mint/types/query.pb.gw.go b/x/mint/types/query.pb.gw.go index c70c3e60b077..cda5db851384 100644 --- a/x/mint/types/query.pb.gw.go +++ b/x/mint/types/query.pb.gw.go @@ -13,7 +13,6 @@ import ( "io" "net/http" - "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -23,13 +22,11 @@ import ( "google.golang.org/grpc/status" ) -// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryParamsRequest @@ -40,15 +37,6 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } -func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryParamsRequest - var metadata runtime.ServerMetadata - - msg, err := server.Params(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_Inflation_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryInflationRequest var metadata runtime.ServerMetadata @@ -58,15 +46,6 @@ func request_Query_Inflation_0(ctx context.Context, marshaler runtime.Marshaler, } -func local_request_Query_Inflation_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryInflationRequest - var metadata runtime.ServerMetadata - - msg, err := server.Inflation(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_AnnualProvisions_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryAnnualProvisionsRequest var metadata runtime.ServerMetadata @@ -76,84 +55,6 @@ func request_Query_AnnualProvisions_0(ctx context.Context, marshaler runtime.Mar } -func local_request_Query_AnnualProvisions_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryAnnualProvisionsRequest - var metadata runtime.ServerMetadata - - msg, err := server.AnnualProvisions(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". -// UnaryRPC :call QueryServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. -func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { - - mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Inflation_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Inflation_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Inflation_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_AnnualProvisions_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_AnnualProvisions_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_AnnualProvisions_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/params/types/proposal/params.pb.go b/x/params/types/proposal/params.pb.go index 68b2f8782066..1681b3960e63 100644 --- a/x/params/types/proposal/params.pb.go +++ b/x/params/types/proposal/params.pb.go @@ -510,10 +510,7 @@ func (m *ParameterChangeProposal) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthParams - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthParams } if (iNdEx + skippy) > l { @@ -659,10 +656,7 @@ func (m *ParamChange) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthParams - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthParams } if (iNdEx + skippy) > l { diff --git a/x/params/types/proposal/query.pb.go b/x/params/types/proposal/query.pb.go index 40bdab3960ce..e0c770d70e24 100644 --- a/x/params/types/proposal/query.pb.go +++ b/x/params/types/proposal/query.pb.go @@ -460,10 +460,7 @@ func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -546,10 +543,7 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { diff --git a/x/params/types/proposal/query.pb.gw.go b/x/params/types/proposal/query.pb.gw.go index c7fab13fca65..9cce0aaaa4bb 100644 --- a/x/params/types/proposal/query.pb.gw.go +++ b/x/params/types/proposal/query.pb.gw.go @@ -13,7 +13,6 @@ import ( "io" "net/http" - "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -23,13 +22,11 @@ import ( "google.golang.org/grpc/status" ) -// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage var ( filter_Query_Params_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} @@ -51,51 +48,6 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } -func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryParamsRequest - 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_Params_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.Params(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". -// UnaryRPC :call QueryServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. -func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { - - mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/slashing/types/genesis.pb.go b/x/slashing/types/genesis.pb.go index 2a600bdb6c44..9819899d095e 100644 --- a/x/slashing/types/genesis.pb.go +++ b/x/slashing/types/genesis.pb.go @@ -705,10 +705,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { @@ -823,10 +820,7 @@ func (m *SigningInfo) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { @@ -942,10 +936,7 @@ func (m *ValidatorMissedBlocks) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { @@ -1034,10 +1025,7 @@ func (m *MissedBlock) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { diff --git a/x/slashing/types/query.pb.go b/x/slashing/types/query.pb.go index 31f168becf3b..3a0c997a3056 100644 --- a/x/slashing/types/query.pb.go +++ b/x/slashing/types/query.pb.go @@ -846,10 +846,7 @@ func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -932,10 +929,7 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1017,10 +1011,7 @@ func (m *QuerySigningInfoRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1103,10 +1094,7 @@ func (m *QuerySigningInfoResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1192,10 +1180,7 @@ func (m *QuerySigningInfosRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1315,10 +1300,7 @@ func (m *QuerySigningInfosResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { diff --git a/x/slashing/types/query.pb.gw.go b/x/slashing/types/query.pb.gw.go index 083fe73aa9f5..56c0cd19e4c5 100644 --- a/x/slashing/types/query.pb.gw.go +++ b/x/slashing/types/query.pb.gw.go @@ -13,7 +13,6 @@ import ( "io" "net/http" - "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -23,13 +22,11 @@ import ( "google.golang.org/grpc/status" ) -// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryParamsRequest @@ -40,15 +37,6 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } -func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryParamsRequest - var metadata runtime.ServerMetadata - - msg, err := server.Params(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_SigningInfo_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QuerySigningInfoRequest var metadata runtime.ServerMetadata @@ -76,33 +64,6 @@ func request_Query_SigningInfo_0(ctx context.Context, marshaler runtime.Marshale } -func local_request_Query_SigningInfo_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QuerySigningInfoRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["cons_address"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "cons_address") - } - - protoReq.ConsAddress, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "cons_address", err) - } - - msg, err := server.SigningInfo(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_SigningInfos_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -123,91 +84,6 @@ func request_Query_SigningInfos_0(ctx context.Context, marshaler runtime.Marshal } -func local_request_Query_SigningInfos_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QuerySigningInfosRequest - 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_SigningInfos_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.SigningInfos(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". -// UnaryRPC :call QueryServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. -func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { - - mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_SigningInfo_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_SigningInfo_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_SigningInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_SigningInfos_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_SigningInfos_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_SigningInfos_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/slashing/types/slashing.pb.go b/x/slashing/types/slashing.pb.go index 87d3baf7c316..d1607badbd33 100644 --- a/x/slashing/types/slashing.pb.go +++ b/x/slashing/types/slashing.pb.go @@ -674,10 +674,7 @@ func (m *ValidatorSigningInfo) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSlashing - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSlashing } if (iNdEx + skippy) > l { @@ -878,10 +875,7 @@ func (m *Params) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthSlashing - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthSlashing } if (iNdEx + skippy) > l { diff --git a/x/slashing/types/tx.pb.go b/x/slashing/types/tx.pb.go index 8412b3291beb..ed6dbcd170ab 100644 --- a/x/slashing/types/tx.pb.go +++ b/x/slashing/types/tx.pb.go @@ -422,10 +422,7 @@ func (m *MsgUnjail) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -475,10 +472,7 @@ func (m *MsgUnjailResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { diff --git a/x/staking/types/genesis.pb.go b/x/staking/types/genesis.pb.go index 1f81d9fed41d..2ea6f8bf9964 100644 --- a/x/staking/types/genesis.pb.go +++ b/x/staking/types/genesis.pb.go @@ -740,10 +740,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { @@ -844,10 +841,7 @@ func (m *LastValidatorPower) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { diff --git a/x/staking/types/query.pb.go b/x/staking/types/query.pb.go index 0df0d02b0fd7..29f84adc27ac 100644 --- a/x/staking/types/query.pb.go +++ b/x/staking/types/query.pb.go @@ -3750,10 +3750,7 @@ func (m *QueryValidatorsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3873,10 +3870,7 @@ func (m *QueryValidatorsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -3958,10 +3952,7 @@ func (m *QueryValidatorRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -4044,10 +4035,7 @@ func (m *QueryValidatorResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -4165,10 +4153,7 @@ func (m *QueryValidatorDelegationsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -4288,10 +4273,7 @@ func (m *QueryValidatorDelegationsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -4409,10 +4391,7 @@ func (m *QueryValidatorUnbondingDelegationsRequest) Unmarshal(dAtA []byte) error if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -4532,10 +4511,7 @@ func (m *QueryValidatorUnbondingDelegationsResponse) Unmarshal(dAtA []byte) erro if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -4649,10 +4625,7 @@ func (m *QueryDelegationRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -4738,10 +4711,7 @@ func (m *QueryDelegationResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -4855,10 +4825,7 @@ func (m *QueryUnbondingDelegationRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -4941,10 +4908,7 @@ func (m *QueryUnbondingDelegationResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -5062,10 +5026,7 @@ func (m *QueryDelegatorDelegationsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -5185,10 +5146,7 @@ func (m *QueryDelegatorDelegationsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -5306,10 +5264,7 @@ func (m *QueryDelegatorUnbondingDelegationsRequest) Unmarshal(dAtA []byte) error if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -5429,10 +5384,7 @@ func (m *QueryDelegatorUnbondingDelegationsResponse) Unmarshal(dAtA []byte) erro if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -5614,10 +5566,7 @@ func (m *QueryRedelegationsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -5737,10 +5686,7 @@ func (m *QueryRedelegationsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -5858,10 +5804,7 @@ func (m *QueryDelegatorValidatorsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -5981,10 +5924,7 @@ func (m *QueryDelegatorValidatorsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -6098,10 +6038,7 @@ func (m *QueryDelegatorValidatorRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -6184,10 +6121,7 @@ func (m *QueryDelegatorValidatorResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -6256,10 +6190,7 @@ func (m *QueryHistoricalInfoRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -6345,10 +6276,7 @@ func (m *QueryHistoricalInfoResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -6398,10 +6326,7 @@ func (m *QueryPoolRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -6484,10 +6409,7 @@ func (m *QueryPoolResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -6537,10 +6459,7 @@ func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -6623,10 +6542,7 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { diff --git a/x/staking/types/query.pb.gw.go b/x/staking/types/query.pb.gw.go index eecdb3f3168d..1d399d8793d6 100644 --- a/x/staking/types/query.pb.gw.go +++ b/x/staking/types/query.pb.gw.go @@ -13,7 +13,6 @@ import ( "io" "net/http" - "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -23,13 +22,11 @@ import ( "google.golang.org/grpc/status" ) -// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage var ( filter_Query_Validators_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} @@ -51,22 +48,6 @@ func request_Query_Validators_0(ctx context.Context, marshaler runtime.Marshaler } -func local_request_Query_Validators_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryValidatorsRequest - 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_Validators_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.Validators(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_Validator_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryValidatorRequest var metadata runtime.ServerMetadata @@ -94,33 +75,6 @@ func request_Query_Validator_0(ctx context.Context, marshaler runtime.Marshaler, } -func local_request_Query_Validator_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryValidatorRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["validator_addr"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") - } - - protoReq.ValidatorAddr, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) - } - - msg, err := server.Validator(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_ValidatorDelegations_0 = &utilities.DoubleArray{Encoding: map[string]int{"validator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -159,40 +113,6 @@ func request_Query_ValidatorDelegations_0(ctx context.Context, marshaler runtime } -func local_request_Query_ValidatorDelegations_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryValidatorDelegationsRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["validator_addr"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") - } - - protoReq.ValidatorAddr, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) - } - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ValidatorDelegations_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ValidatorDelegations(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_ValidatorUnbondingDelegations_0 = &utilities.DoubleArray{Encoding: map[string]int{"validator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -231,40 +151,6 @@ func request_Query_ValidatorUnbondingDelegations_0(ctx context.Context, marshale } -func local_request_Query_ValidatorUnbondingDelegations_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryValidatorUnbondingDelegationsRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["validator_addr"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") - } - - protoReq.ValidatorAddr, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) - } - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ValidatorUnbondingDelegations_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ValidatorUnbondingDelegations(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_Delegation_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryDelegationRequest var metadata runtime.ServerMetadata @@ -303,44 +189,6 @@ func request_Query_Delegation_0(ctx context.Context, marshaler runtime.Marshaler } -func local_request_Query_Delegation_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDelegationRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["validator_addr"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") - } - - protoReq.ValidatorAddr, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) - } - - val, ok = pathParams["delegator_addr"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_addr") - } - - protoReq.DelegatorAddr, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_addr", err) - } - - msg, err := server.Delegation(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_UnbondingDelegation_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryUnbondingDelegationRequest var metadata runtime.ServerMetadata @@ -379,44 +227,6 @@ func request_Query_UnbondingDelegation_0(ctx context.Context, marshaler runtime. } -func local_request_Query_UnbondingDelegation_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryUnbondingDelegationRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["validator_addr"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") - } - - protoReq.ValidatorAddr, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) - } - - val, ok = pathParams["delegator_addr"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_addr") - } - - protoReq.DelegatorAddr, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_addr", err) - } - - msg, err := server.UnbondingDelegation(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_DelegatorDelegations_0 = &utilities.DoubleArray{Encoding: map[string]int{"delegator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -455,8 +265,12 @@ func request_Query_DelegatorDelegations_0(ctx context.Context, marshaler runtime } -func local_request_Query_DelegatorDelegations_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDelegatorDelegationsRequest +var ( + filter_Query_DelegatorUnbondingDelegations_0 = &utilities.DoubleArray{Encoding: map[string]int{"delegator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_DelegatorUnbondingDelegations_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDelegatorUnbondingDelegationsRequest var metadata runtime.ServerMetadata var ( @@ -480,21 +294,21 @@ func local_request_Query_DelegatorDelegations_0(ctx context.Context, marshaler r if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DelegatorDelegations_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DelegatorUnbondingDelegations_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.DelegatorDelegations(ctx, &protoReq) + msg, err := client.DelegatorUnbondingDelegations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } var ( - filter_Query_DelegatorUnbondingDelegations_0 = &utilities.DoubleArray{Encoding: map[string]int{"delegator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} + filter_Query_Redelegations_0 = &utilities.DoubleArray{Encoding: map[string]int{"delegator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) -func request_Query_DelegatorUnbondingDelegations_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDelegatorUnbondingDelegationsRequest +func request_Query_Redelegations_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryRedelegationsRequest var metadata runtime.ServerMetadata var ( @@ -518,17 +332,21 @@ func request_Query_DelegatorUnbondingDelegations_0(ctx context.Context, marshale if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DelegatorUnbondingDelegations_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Redelegations_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.DelegatorUnbondingDelegations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.Redelegations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func local_request_Query_DelegatorUnbondingDelegations_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDelegatorUnbondingDelegationsRequest +var ( + filter_Query_DelegatorValidators_0 = &utilities.DoubleArray{Encoding: map[string]int{"delegator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_DelegatorValidators_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDelegatorValidatorsRequest var metadata runtime.ServerMetadata var ( @@ -552,21 +370,17 @@ func local_request_Query_DelegatorUnbondingDelegations_0(ctx context.Context, ma if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DelegatorUnbondingDelegations_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DelegatorValidators_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.DelegatorUnbondingDelegations(ctx, &protoReq) + msg, err := client.DelegatorValidators(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -var ( - filter_Query_Redelegations_0 = &utilities.DoubleArray{Encoding: map[string]int{"delegator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} -) - -func request_Query_Redelegations_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryRedelegationsRequest +func request_Query_DelegatorValidator_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDelegatorValidatorRequest var metadata runtime.ServerMetadata var ( @@ -587,20 +401,24 @@ func request_Query_Redelegations_0(ctx context.Context, marshaler runtime.Marsha return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_addr", err) } - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Redelegations_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) } - msg, err := client.Redelegations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.DelegatorValidator(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func local_request_Query_Redelegations_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryRedelegationsRequest +func request_Query_HistoricalInfo_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryHistoricalInfoRequest var metadata runtime.ServerMetadata var ( @@ -610,233 +428,24 @@ func local_request_Query_Redelegations_0(ctx context.Context, marshaler runtime. _ = err ) - val, ok = pathParams["delegator_addr"] + val, ok = pathParams["height"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_addr") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "height") } - protoReq.DelegatorAddr, err = runtime.String(val) + protoReq.Height, err = runtime.Int64(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_addr", err) - } - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Redelegations_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "height", err) } - msg, err := server.Redelegations(ctx, &protoReq) + msg, err := client.HistoricalInfo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -var ( - filter_Query_DelegatorValidators_0 = &utilities.DoubleArray{Encoding: map[string]int{"delegator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} -) - -func request_Query_DelegatorValidators_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDelegatorValidatorsRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["delegator_addr"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_addr") - } - - protoReq.DelegatorAddr, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_addr", err) - } - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DelegatorValidators_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.DelegatorValidators(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Query_DelegatorValidators_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDelegatorValidatorsRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["delegator_addr"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_addr") - } - - protoReq.DelegatorAddr, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_addr", err) - } - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DelegatorValidators_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.DelegatorValidators(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Query_DelegatorValidator_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDelegatorValidatorRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["delegator_addr"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_addr") - } - - protoReq.DelegatorAddr, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_addr", err) - } - - val, ok = pathParams["validator_addr"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") - } - - protoReq.ValidatorAddr, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) - } - - msg, err := client.DelegatorValidator(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Query_DelegatorValidator_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDelegatorValidatorRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["delegator_addr"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_addr") - } - - protoReq.DelegatorAddr, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_addr", err) - } - - val, ok = pathParams["validator_addr"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") - } - - protoReq.ValidatorAddr, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) - } - - msg, err := server.DelegatorValidator(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Query_HistoricalInfo_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryHistoricalInfoRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["height"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "height") - } - - protoReq.Height, err = runtime.Int64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "height", err) - } - - msg, err := client.HistoricalInfo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Query_HistoricalInfo_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryHistoricalInfoRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["height"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "height") - } - - protoReq.Height, err = runtime.Int64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "height", err) - } - - msg, err := server.HistoricalInfo(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Query_Pool_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPoolRequest +func request_Query_Pool_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPoolRequest var metadata runtime.ServerMetadata msg, err := client.Pool(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) @@ -844,15 +453,6 @@ func request_Query_Pool_0(ctx context.Context, marshaler runtime.Marshaler, clie } -func local_request_Query_Pool_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPoolRequest - var metadata runtime.ServerMetadata - - msg, err := server.Pool(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryParamsRequest var metadata runtime.ServerMetadata @@ -862,304 +462,6 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } -func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryParamsRequest - var metadata runtime.ServerMetadata - - msg, err := server.Params(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". -// UnaryRPC :call QueryServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. -func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { - - mux.Handle("GET", pattern_Query_Validators_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Validators_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Validators_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Validator_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Validator_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Validator_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_ValidatorDelegations_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_ValidatorDelegations_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ValidatorDelegations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_ValidatorUnbondingDelegations_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_ValidatorUnbondingDelegations_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ValidatorUnbondingDelegations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Delegation_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Delegation_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Delegation_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_UnbondingDelegation_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_UnbondingDelegation_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_UnbondingDelegation_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_DelegatorDelegations_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_DelegatorDelegations_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_DelegatorDelegations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_DelegatorUnbondingDelegations_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_DelegatorUnbondingDelegations_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_DelegatorUnbondingDelegations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Redelegations_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Redelegations_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Redelegations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_DelegatorValidators_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_DelegatorValidators_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_DelegatorValidators_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_DelegatorValidator_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_DelegatorValidator_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_DelegatorValidator_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_HistoricalInfo_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_HistoricalInfo_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_HistoricalInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Pool_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Pool_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Pool_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/staking/types/staking.pb.go b/x/staking/types/staking.pb.go index 4dbe0e3e300d..b97e1224c45a 100644 --- a/x/staking/types/staking.pb.go +++ b/x/staking/types/staking.pb.go @@ -3602,10 +3602,7 @@ func (m *HistoricalInfo) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -3757,10 +3754,7 @@ func (m *CommissionRates) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -3876,10 +3870,7 @@ func (m *Commission) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -4089,10 +4080,7 @@ func (m *Description) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -4469,10 +4457,7 @@ func (m *Validator) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -4554,10 +4539,7 @@ func (m *ValAddresses) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -4671,10 +4653,7 @@ func (m *DVPair) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -4758,10 +4737,7 @@ func (m *DVPairs) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -4907,10 +4883,7 @@ func (m *DVVTriplet) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -4994,10 +4967,7 @@ func (m *DVVTriplets) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -5145,10 +5115,7 @@ func (m *Delegation) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -5296,10 +5263,7 @@ func (m *UnbondingDelegation) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -5469,10 +5433,7 @@ func (m *UnbondingDelegationEntry) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -5642,10 +5603,7 @@ func (m *RedelegationEntry) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -5825,10 +5783,7 @@ func (m *Redelegation) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -6000,10 +5955,7 @@ func (m *Params) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -6119,10 +6071,7 @@ func (m *DelegationResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -6239,10 +6188,7 @@ func (m *RedelegationEntryResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -6359,10 +6305,7 @@ func (m *RedelegationResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { @@ -6480,10 +6423,7 @@ func (m *Pool) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthStaking - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthStaking } if (iNdEx + skippy) > l { diff --git a/x/staking/types/tx.pb.go b/x/staking/types/tx.pb.go index f4a4f3c6864c..50e1765ff6c0 100644 --- a/x/staking/types/tx.pb.go +++ b/x/staking/types/tx.pb.go @@ -1642,10 +1642,7 @@ func (m *MsgCreateValidator) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1695,10 +1692,7 @@ func (m *MsgCreateValidatorResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1885,10 +1879,7 @@ func (m *MsgEditValidator) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1938,10 +1929,7 @@ func (m *MsgEditValidatorResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2088,10 +2076,7 @@ func (m *MsgDelegate) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2141,10 +2126,7 @@ func (m *MsgDelegateResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2323,10 +2305,7 @@ func (m *MsgBeginRedelegate) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2409,10 +2388,7 @@ func (m *MsgBeginRedelegateResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2559,10 +2535,7 @@ func (m *MsgUndelegate) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -2645,10 +2618,7 @@ func (m *MsgUndelegateResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { diff --git a/x/upgrade/types/query.pb.go b/x/upgrade/types/query.pb.go index 3c49f6c4ade5..40caf74e8f6d 100644 --- a/x/upgrade/types/query.pb.go +++ b/x/upgrade/types/query.pb.go @@ -817,10 +817,7 @@ func (m *QueryCurrentPlanRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -906,10 +903,7 @@ func (m *QueryCurrentPlanResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -991,10 +985,7 @@ func (m *QueryAppliedPlanRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1063,10 +1054,7 @@ func (m *QueryAppliedPlanResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1135,10 +1123,7 @@ func (m *QueryUpgradedConsensusStateRequest) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { @@ -1224,10 +1209,7 @@ func (m *QueryUpgradedConsensusStateResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthQuery } if (iNdEx + skippy) > l { diff --git a/x/upgrade/types/query.pb.gw.go b/x/upgrade/types/query.pb.gw.go index cf1f9def8eee..afccefd1cc01 100644 --- a/x/upgrade/types/query.pb.gw.go +++ b/x/upgrade/types/query.pb.gw.go @@ -13,7 +13,6 @@ import ( "io" "net/http" - "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -23,13 +22,11 @@ import ( "google.golang.org/grpc/status" ) -// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage func request_Query_CurrentPlan_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryCurrentPlanRequest @@ -40,15 +37,6 @@ func request_Query_CurrentPlan_0(ctx context.Context, marshaler runtime.Marshale } -func local_request_Query_CurrentPlan_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryCurrentPlanRequest - var metadata runtime.ServerMetadata - - msg, err := server.CurrentPlan(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_AppliedPlan_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryAppliedPlanRequest var metadata runtime.ServerMetadata @@ -76,33 +64,6 @@ func request_Query_AppliedPlan_0(ctx context.Context, marshaler runtime.Marshale } -func local_request_Query_AppliedPlan_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryAppliedPlanRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["name"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name") - } - - protoReq.Name, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err) - } - - msg, err := server.AppliedPlan(ctx, &protoReq) - return msg, metadata, err - -} - func request_Query_UpgradedConsensusState_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryUpgradedConsensusStateRequest var metadata runtime.ServerMetadata @@ -130,102 +91,6 @@ func request_Query_UpgradedConsensusState_0(ctx context.Context, marshaler runti } -func local_request_Query_UpgradedConsensusState_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryUpgradedConsensusStateRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["last_height"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "last_height") - } - - protoReq.LastHeight, err = runtime.Int64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "last_height", err) - } - - msg, err := server.UpgradedConsensusState(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". -// UnaryRPC :call QueryServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. -func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { - - mux.Handle("GET", pattern_Query_CurrentPlan_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_CurrentPlan_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_CurrentPlan_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_AppliedPlan_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_AppliedPlan_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_AppliedPlan_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_UpgradedConsensusState_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.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_UpgradedConsensusState_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_UpgradedConsensusState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/upgrade/types/upgrade.pb.go b/x/upgrade/types/upgrade.pb.go index cb608f874747..642f4446fe28 100644 --- a/x/upgrade/types/upgrade.pb.go +++ b/x/upgrade/types/upgrade.pb.go @@ -712,10 +712,7 @@ func (m *Plan) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUpgrade - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUpgrade } if (iNdEx + skippy) > l { @@ -862,10 +859,7 @@ func (m *SoftwareUpgradeProposal) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUpgrade - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUpgrade } if (iNdEx + skippy) > l { @@ -979,10 +973,7 @@ func (m *CancelSoftwareUpgradeProposal) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthUpgrade - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthUpgrade } if (iNdEx + skippy) > l { From df95ca8826ed1d669328c25e913eda8a725f6b9e Mon Sep 17 00:00:00 2001 From: Cyrus Goh Date: Fri, 15 Jan 2021 13:37:47 -0800 Subject: [PATCH 039/152] Update ga id (#8351) --- docs/.vuepress/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 0c487c3ee021..ce94542714cd 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -196,7 +196,7 @@ module.exports = { [ "@vuepress/google-analytics", { - ga: "UA-51029217-12" + ga: "UA-51029217-2" } ], [ From d39c42c987738d4dd7bd89c35563eb1a32389183 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Sat, 16 Jan 2021 00:03:08 +0100 Subject: [PATCH 040/152] Robert/docs slashing (#8329) * update slashing docs * x/slashing docs general audit & cleanup * Update x/slashing/spec/02_state.md Co-authored-by: Amaury * Update x/slashing/spec/05_hooks.md Co-authored-by: Alessio Treglia * use code insertion widget * review update * Update x/slashing/spec/05_hooks.md Co-authored-by: Alessio Treglia * update link and location for fee distribution spec Co-authored-by: Amaury Co-authored-by: Alessio Treglia --- docs/migrations/rest.md | 2 +- docs/run-node/interact-node.md | 2 +- docs/run-node/txs.md | 19 +++---- docs/spec/_proposals/README.md | 3 - .../f1_fee_distr.pdf | Bin .../f1_fee_distr.tex | 0 proto/cosmos/slashing/v1beta1/slashing.proto | 15 +++-- x/slashing/spec/02_state.md | 53 +++++------------- x/slashing/spec/03_messages.md | 9 ++- x/slashing/spec/05_hooks.md | 13 ++++- x/slashing/spec/06_events.md | 30 +++++++--- x/slashing/spec/07_tombstone.md | 10 ++-- x/slashing/spec/08_params.md | 14 ++--- 13 files changed, 88 insertions(+), 82 deletions(-) delete mode 100644 docs/spec/_proposals/README.md rename docs/spec/{_proposals/f1-fee-distribution => fee_distribution}/f1_fee_distr.pdf (100%) rename docs/spec/{_proposals/f1-fee-distribution => fee_distribution}/f1_fee_distr.tex (100%) diff --git a/docs/migrations/rest.md b/docs/migrations/rest.md index 3af7e8ee2c58..b1675543eb05 100644 --- a/docs/migrations/rest.md +++ b/docs/migrations/rest.md @@ -32,7 +32,7 @@ Some important information concerning all legacy REST endpoints: ## Migrating to New REST Endpoints -Thanks to the Protocol Buffers migration in v0.40 we are able to take advantage of a vast number of gRPC tools and solutions. For most of the legacy REST endpoints, Cosmos SDK v0.40 provides new REST endpoints generated from [gRPC `Query` services](../building-modules/query-services.md) using [grpc-gateway](https://grpc-ecosystem.github.io/grpc-gateway/). We usually call them _gGPC-gateway REST endpoints_. +Thanks to the Protocol Buffers migration in v0.40, we are able to take advantage of a vast number of gRPC tools and solutions. For most of the legacy REST endpoints, Cosmos SDK v0.40 provides new REST endpoints generated from [gRPC `Query` services](../building-modules/query-services.md) using [grpc-gateway](https://grpc-ecosystem.github.io/grpc-gateway/). We usually call them _gGPC-gateway REST endpoints_. Some modules expose legacy `POST` endpoints to generate unsigned transactions for their `Msg`s. These `POST` endpoints have been removed. We recommend to use [service `Msg`s](../building-modules/msg-services.md) directly, and use Protobuf to do client-side transaction generation. A guide can be found [here](../run-node/txs.md). diff --git a/docs/run-node/interact-node.md b/docs/run-node/interact-node.md index 60ce6c2ed591..c7b30c57b073 100644 --- a/docs/run-node/interact-node.md +++ b/docs/run-node/interact-node.md @@ -139,7 +139,7 @@ func queryState() error { // Create a connection to the gRPC server. grpcConn := grpc.Dial( - "127.0.0.1:9090", // Or your gRPC server address. + "127.0.0.1:9090", // your gRPC server address. grpc.WithInsecure(), // The SDK doesn't support any transport security mechanism. ) defer grpcConn.Close() diff --git a/docs/run-node/txs.md b/docs/run-node/txs.md index 0c4c9de47ccf..9fbc642efc9d 100644 --- a/docs/run-node/txs.md +++ b/docs/run-node/txs.md @@ -18,7 +18,7 @@ will run the following steps: - generate a transaction with one `Msg` (`x/bank`'s `MsgSend`), and print the generated transaction to the console. - ask the user for confirmation to send the transaction from the `$MY_VALIDATOR_ADDRESS` account. -- fetch `$MY_VALIDATOR_ADDRESS` in the keyring. This is possible because we have [set up the CLI's keyring](./keyring.md) in a previous step. +- fetch `$MY_VALIDATOR_ADDRESS` from the keyring. This is possible because we have [set up the CLI's keyring](./keyring.md) in a previous step. - sign the generated transaction with the keyring's account. - broadcast the signed transaction to the network. This is possible because the CLI connects to the node's Tendermint RPC endpoint. @@ -52,7 +52,7 @@ Some useful flags to consider in the `tx sign` command: #### Signing with Multiple Signers ::: warning -Please note that signing a transaction with multiple signers or with a multisig account, where at least one signer uses `SIGN_MODE_DIRECT`, is not possible as of yet. You may follow [this Github issue](https://github.com/cosmos/cosmos-sdk/issues/8141) for more info. +Please note that signing a transaction with multiple signers or with a multisig account, where at least one signer uses `SIGN_MODE_DIRECT`, is not yet possible. You may follow [this Github issue](https://github.com/cosmos/cosmos-sdk/issues/8141) for more info. ::: Signing with multiple signers is done with the `tx multisign` command. This command assumes that all signers use `SIGN_MODE_LEGACY_AMINO_JSON`. The flow is similar to the `tx sign` command flow, but instead of signing an unsigned transaction file, each signer signs the file signed by previous signer(s). The `tx multisign` command will append signatures to the existing transactions. It is important that signers sign the transaction **in the same order** as given by the transaction, which is retrievable using the `GetSigners()` method. @@ -60,14 +60,13 @@ Signing with multiple signers is done with the `tx multisign` command. This comm For example, starting with the `unsigned_tx.json`, and assuming the transaction has 4 signers, we would run: ```bash -# Let signer 1 sign the unsigned tx. +# Let signer1 sign the unsigned tx. simd tx multisignsign unsigned_tx.json signer_key_1 --chain-id my-test-chain --keyring-backend test > partial_tx_1.json -# Signer 2 appends their signature. +# Now signer1 will send the partial_tx_1.json to the signer2. +# Signer2 appends their signature: simd tx multisignsign partial_tx_1.json signer_key_2 --chain-id my-test-chain --keyring-backend test > partial_tx_2.json -# Signer 3 appends their signature. +# Signer2 sends the partial_tx_2.json file to signer3, and signer3 can append his signature: simd tx multisignsign partial_tx_2.json signer_key_3 --chain-id my-test-chain --keyring-backend test > partial_tx_3.json -# Signer 4 appends their signature. The final output is the fully signed tx. -simd tx multisignsign partial_tx_3.json signer_key_4 --chain-id my-test-chain --keyring-backend test > signed_tx.json ``` ### Broadcasting a Transaction @@ -154,7 +153,7 @@ At this point, `TxBuilder`'s underlying transaction is ready to be signed. ### Signing a Transaction -We chose our encoding config to use Protobuf, which will use `SIGN_MODE_DIRECT` by default. As per [ADR-020](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc6/docs/architecture/adr-020-protobuf-transaction-encoding.md), each signer needs to sign the `SignerInfo`s of all other signers. This means that we need to perform two steps sequentially: +We set encoding config to use Protobuf, which will use `SIGN_MODE_DIRECT` by default. As per [ADR-020](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc6/docs/architecture/adr-020-protobuf-transaction-encoding.md), each signer needs to sign the `SignerInfo`s of all other signers. This means that we need to perform two steps sequentially: - for each signer, populate the signer's `SignerInfo` inside `TxBuilder`, - once all `SignerInfo`s are populated, for each signer, sign the `SignDoc` (the payload to be signed). @@ -254,7 +253,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/tx" ) -func sendTx() error { +func sendTx(ctx context.Context) error { // --snip-- // Create a connection to the gRPC server. @@ -269,7 +268,7 @@ func sendTx() error { txClient := tx.NewServiceClient(grpcConn) // We then call the BroadcastTx method on this client. grpcRes, err := txClient.BroadcastTx( - context.Background(), + ctx, &tx.BroadcastTxRequest{ Mode: tx.BroadcastMode_BROADCAST_MODE_SYNC, TxBytes: txBytes, // Proto-binary of the signed transaction, see previous step. diff --git a/docs/spec/_proposals/README.md b/docs/spec/_proposals/README.md deleted file mode 100644 index 213d6288cb70..000000000000 --- a/docs/spec/_proposals/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Spec Proposals - -- [F1 Fee Distribution](./f1-fee-distribution/f1_fee_distr.pdf) \ No newline at end of file diff --git a/docs/spec/_proposals/f1-fee-distribution/f1_fee_distr.pdf b/docs/spec/fee_distribution/f1_fee_distr.pdf similarity index 100% rename from docs/spec/_proposals/f1-fee-distribution/f1_fee_distr.pdf rename to docs/spec/fee_distribution/f1_fee_distr.pdf diff --git a/docs/spec/_proposals/f1-fee-distribution/f1_fee_distr.tex b/docs/spec/fee_distribution/f1_fee_distr.tex similarity index 100% rename from docs/spec/_proposals/f1-fee-distribution/f1_fee_distr.tex rename to docs/spec/fee_distribution/f1_fee_distr.tex diff --git a/proto/cosmos/slashing/v1beta1/slashing.proto b/proto/cosmos/slashing/v1beta1/slashing.proto index 657a90f1bd05..882a0fb60cb5 100644 --- a/proto/cosmos/slashing/v1beta1/slashing.proto +++ b/proto/cosmos/slashing/v1beta1/slashing.proto @@ -15,17 +15,20 @@ message ValidatorSigningInfo { option (gogoproto.goproto_stringer) = false; string address = 1; - // height at which validator was first a candidate OR was unjailed + // Height at which validator was first a candidate OR was unjailed int64 start_height = 2 [(gogoproto.moretags) = "yaml:\"start_height\""]; - // index offset into signed block bit array + // Index which is incremented each time the validator was a bonded + // in a block and may have signed a precommit or not. This in conjunction with the + // `SignedBlocksWindow` param determines the index in the `MissedBlocksBitArray`. int64 index_offset = 3 [(gogoproto.moretags) = "yaml:\"index_offset\""]; - // timestamp validator cannot be unjailed until + // Timestamp until which the validator is jailed due to liveness downtime. google.protobuf.Timestamp jailed_until = 4 [(gogoproto.moretags) = "yaml:\"jailed_until\"", (gogoproto.stdtime) = true, (gogoproto.nullable) = false]; - // whether or not a validator has been tombstoned (killed out of validator - // set) + // Whether or not a validator has been tombstoned (killed out of validator set). It is set + // once the validator commits an equivocation or for any other configured misbehiavor. bool tombstoned = 5; - // missed blocks counter (to avoid scanning the array every time) + // A counter kept to avoid unnecessary array reads. + // Note that `Sum(MissedBlocksBitArray)` always equals `MissedBlocksCounter`. int64 missed_blocks_counter = 6 [(gogoproto.moretags) = "yaml:\"missed_blocks_counter\""]; } diff --git a/x/slashing/spec/02_state.md b/x/slashing/spec/02_state.md index 17931ce866a0..3644ff9651e9 100644 --- a/x/slashing/spec/02_state.md +++ b/x/slashing/spec/02_state.md @@ -10,9 +10,16 @@ Every block includes a set of precommits by the validators for the previous bloc known as the `LastCommitInfo` provided by Tendermint. A `LastCommitInfo` is valid so long as it contains precommits from +2/3 of total voting power. -Proposers are incentivized to include precommits from all validators in the `LastCommitInfo` +Proposers are incentivized to include precommits from all validators in the Tendermint `LastCommitInfo` by receiving additional fees proportional to the difference between the voting -power included in the `LastCommitInfo` and +2/3 (see [TODO](https://github.com/cosmos/cosmos-sdk/issues/967)). +power included in the `LastCommitInfo` and +2/3 (see [fee distribution](https://github.com/cosmos/cosmos-sdk/blob/master/docs/spec/fee_distribution)). + +``` +type LastCommitInfo struct { + Round int32 + Votes []VoteInfo +} +``` Validators are penalized for failing to be included in the `LastCommitInfo` for some number of blocks by being automatically jailed, potentially slashed, and unbonded. @@ -20,15 +27,16 @@ number of blocks by being automatically jailed, potentially slashed, and unbonde Information about validator's liveness activity is tracked through `ValidatorSigningInfo`. It is indexed in the store as follows: -- ValidatorSigningInfo: ` 0x01 | ConsAddress -> amino(valSigningInfo)` -- MissedBlocksBitArray: ` 0x02 | ConsAddress | LittleEndianUint64(signArrayIndex) -> VarInt(didMiss)` +- ValidatorSigningInfo: ` 0x01 | ConsAddress -> ProtocolBuffer(ValSigningInfo)` +- MissedBlocksBitArray: ` 0x02 | ConsAddress | LittleEndianUint64(signArrayIndex) -> VarInt(didMiss)` (varint is a number encoding format) The first mapping allows us to easily lookup the recent signing info for a -validator based on the validator's consensus address. The second mapping acts +validator based on the validator's consensus address. + +The second mapping (`MissedBlocksBitArray`) acts as a bit-array of size `SignedBlocksWindow` that tells us if the validator missed the block for a given index in the bit-array. The index in the bit-array is given as little endian uint64. - The result is a `varint` that takes on `0` or `1`, where `0` indicates the validator did not miss (did sign) the corresponding block, and `1` indicates they missed the block (did not sign). @@ -40,35 +48,4 @@ bonded validator. The `SignedBlocksWindow` parameter defines the size The information stored for tracking validator liveness is as follows: -```protobuf -// ValidatorSigningInfo defines a validator's signing info for monitoring their -// liveness activity. -message ValidatorSigningInfo { - string address = 1; - // height at which validator was first a candidate OR was unjailed - int64 start_height = 2; - // index offset into signed block bit array - int64 index_offset = 3; - // timestamp validator cannot be unjailed until - google.protobuf.Timestamp jailed_until = 4; - // whether or not a validator has been tombstoned (killed out of validator - // set) - bool tombstoned = 5; - // missed blocks counter (to avoid scanning the array every time) - int64 missed_blocks_counter = 6; -} -``` - -Where: - -- **Address**: The validator's consensus address. -- **StartHeight**: The height that the candidate became an active validator - (with non-zero voting power). -- **IndexOffset**: Index which is incremented each time the validator was a bonded - in a block and may have signed a precommit or not. This in conjunction with the - `SignedBlocksWindow` param determines the index in the `MissedBlocksBitArray`. -- **JailedUntil**: Time for which the validator is jailed until due to liveness downtime. -- **Tombstoned**: Desribes if the validator is tombstoned or not. It is set once the - validator commits an equivocation or for any other configured misbehiavor. -- **MissedBlocksCounter**: A counter kept to avoid unnecessary array reads. Note - that `Sum(MissedBlocksBitArray)` equals `MissedBlocksCounter` always. ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/slashing/v1beta1/slashing.proto#L11-L33 diff --git a/x/slashing/spec/03_messages.md b/x/slashing/spec/03_messages.md index 6e7d168ffdb5..d680b83cdfee 100644 --- a/x/slashing/spec/03_messages.md +++ b/x/slashing/spec/03_messages.md @@ -20,14 +20,17 @@ message MsgUnjail { } ``` -And below is its corresponding handler: +Below is a pseudocode of the `MsgSrv/Unjail` RPC: ``` -handleMsgUnjail(tx MsgUnjail) +unjail(tx MsgUnjail) validator = getValidator(tx.ValidatorAddr) if validator == nil fail with "No validator found" + if getSelfDelegation(validator) == 0 + fail with "validator must self delegate before unjailing" + if !validator.Jailed fail with "Validator not jailed, cannot unjail" @@ -43,6 +46,6 @@ handleMsgUnjail(tx MsgUnjail) return ``` -If the validator has enough stake to be in the top `n = MaximumBondedValidators`, they will be automatically rebonded, +If the validator has enough stake to be in the top `n = MaximumBondedValidators`, it will be automatically rebonded, and all delegators still delegated to the validator will be rebonded and begin to again collect provisions and rewards. diff --git a/x/slashing/spec/05_hooks.md b/x/slashing/spec/05_hooks.md index 8f78cdff01b0..2e26dfd3d411 100644 --- a/x/slashing/spec/05_hooks.md +++ b/x/slashing/spec/05_hooks.md @@ -4,7 +4,18 @@ order: 5 # Hooks -In this section we describe the "hooks" - slashing module code that runs when other events happen. +This section contains a description of the module's `hooks`. Hooks are operations that are executed automatically when events are raised. + +## Staking hooks + +The slashing module implements the `StakingHooks` defined in `x/staking` and are used as record-keeping of validators information. During the app initialization, these hooks should be registered in the staking module struct. + +The following hooks impact the slashing state: + ++ `AfterValidatorBonded` creates a `ValidatorSigningInfo` instance as described in the following section. ++ `AfterValidatorCreated` stores a validator's consensus key. ++ `AfterValidatorRemoved` removes a validator's consensus key. + ## Validator Bonded diff --git a/x/slashing/spec/06_events.md b/x/slashing/spec/06_events.md index c5fceda51981..cd79a652725c 100644 --- a/x/slashing/spec/06_events.md +++ b/x/slashing/spec/06_events.md @@ -6,7 +6,19 @@ order: 6 The slashing module emits the following events/tags: -## BeginBlocker +## MsgServer + +### MsgUnjail + +| Type | Attribute Key | Attribute Value | +| ------- | ------------- | --------------- | +| message | module | slashing | +| message | sender | {validatorAddress} | + + +## Keeper + +## BeginBlocker: HandleValidatorSignature | Type | Attribute Key | Attribute Value | | ----- | ------------- | --------------------------- | @@ -23,12 +35,14 @@ The slashing module emits the following events/tags: | liveness | missed_blocks | {missedBlocksCounter} | | liveness | height | {blockHeight} | -## Handlers -### MsgUnjail +### Slash -| Type | Attribute Key | Attribute Value | -| ------- | ------------- | --------------- | -| message | module | slashing | -| message | action | unjail | -| message | sender | {senderAddress} | ++ same as `"slash"` event from `HandleValidatorSignature`, but without the `jailed` attribute. + +### Jail + + +| Type | Attribute Key | Attribute Value | +| ----- | ------------- | ------------------ | +| slash | jailed | {validatorAddress} | diff --git a/x/slashing/spec/07_tombstone.md b/x/slashing/spec/07_tombstone.md index 4759a89b7190..216d1836f5a3 100644 --- a/x/slashing/spec/07_tombstone.md +++ b/x/slashing/spec/07_tombstone.md @@ -87,15 +87,17 @@ Currently, in the jail period implementation, once a validator unjails, all of their delegators who are delegated to them (haven't unbonded / redelegated away), stay with them. Given that consensus safety faults are so egregious (way more so than liveness faults), it is probably prudent to have delegators not -"auto-rebond" to the validator. Thus, we propose setting the "jail time" for a +"auto-rebond" to the validator. + +### Proposal: infinite jail + +We propose setting the "jail time" for a validator who commits a consensus safety fault, to `infinite` (i.e. a tombstone state). This essentially kicks the validator out of the validator set and does not allow them to re-enter the validator set. All of their delegators (including the operator themselves) have to either unbond or redelegate away. The validator operator can create a new validator if they would like, with a new operator key and consensus key, but they -have to "re-earn" their delegations back. To put the validator in the tombstone -state, we set `DoubleSignJailEndTime` to `time.Unix(253402300800)`, the maximum -time supported by Amino. +have to "re-earn" their delegations back. Implementing the tombstone system and getting rid of the slashing period tracking will make the `slashing` module way simpler, especially because we can remove all diff --git a/x/slashing/spec/08_params.md b/x/slashing/spec/08_params.md index 0ebfb9e27ef2..defed189ab9e 100644 --- a/x/slashing/spec/08_params.md +++ b/x/slashing/spec/08_params.md @@ -6,10 +6,10 @@ order: 8 The slashing module contains the following parameters: -| Key | Type | Example | -| ----------------------- | ---------------- | ---------------------- | -| SignedBlocksWindow | string (int64) | "100" | -| MinSignedPerWindow | string (dec) | "0.500000000000000000" | -| DowntimeJailDuration | string (time ns) | "600000000000" | -| SlashFractionDoubleSign | string (dec) | "0.050000000000000000" | -| SlashFractionDowntime | string (dec) | "0.010000000000000000" | +| Key | Type | Example | +| ----------------------- | -------------- | ---------------------- | +| SignedBlocksWindow | string (int64) | "100" | +| MinSignedPerWindow | string (dec) | "0.500000000000000000" | +| DowntimeJailDuration | string (ns) | "600000000000" | +| SlashFractionDoubleSign | string (dec) | "0.050000000000000000" | +| SlashFractionDowntime | string (dec) | "0.010000000000000000" | From 43840f45dd93cb9a602364b35cd4073b9ed3c4ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Sat, 16 Jan 2021 13:48:48 +0100 Subject: [PATCH 041/152] Revisions to Unfreezing Clients via Governance ADR (#8343) * revisions to adr 26 decision * Update docs/architecture/adr-026-ibc-client-recovery-mechanisms.md Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Christopher Goes --- .../adr-026-ibc-client-recovery-mechanisms.md | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/docs/architecture/adr-026-ibc-client-recovery-mechanisms.md b/docs/architecture/adr-026-ibc-client-recovery-mechanisms.md index dc34bbf33e9d..424f0415f60f 100644 --- a/docs/architecture/adr-026-ibc-client-recovery-mechanisms.md +++ b/docs/architecture/adr-026-ibc-client-recovery-mechanisms.md @@ -4,10 +4,11 @@ - 2020/06/23: Initial version - 2020/08/06: Revisions per review & to reference version +- 2021/01/15: Revision to support substitute clients for unfreezing ## Status -*Proposed* +*Accepted* ## Context @@ -36,18 +37,22 @@ We elect not to deal with chains which have actually halted, which is necessaril 1. `allow_governance_override_after_expiry` (boolean, default false) 1. Require Tendermint light clients (ICS 07) to expose the following additional internal query functions 1. `Expired() boolean`, which returns whether or not the client has passed the trusting period since the last update (in which case no headers can be validated) -1. Require Tendermint light clients (ICS 07) to expose the following additional state mutation functions - 1. `Unfreeze()`, which unfreezes a light client after misbehaviour and clears any frozen height previously set 1. Require Tendermint light clients (ICS 07) & solo machine clients (ICS 06) to be created with the following additional flags 1. `allow_governance_override_after_misbehaviour` (boolean, default false) +1. Require Tendermint light clients (ICS 07) to expose the following additional state mutation functions + 1. `Unfreeze()`, which unfreezes a light client after misbehaviour and clears any frozen height previously set 1. Add a new governance proposal type, `ClientUpdateProposal`, in the `x/ibc` module - 1. Extend the base `Proposal` with a client identifier (`string`) and a header (`bytes`, encoded in a client-type-specific format) - 1. If this governance proposal passes, the client is updated with the provided header, if and only if: + 1. Extend the base `Proposal` with two client identifiers (`string`) and an initial height ('exported.Height'). + 1. The first client identifier is the proposed client to be updated. This client must be either frozen or expired. + 1. The second client is a substitute client. It carries all the state for the client which may be updated. It must have identitical client and chain parameters to the client which may be updated (except for latest height and frozen height). It should be continually updated during the voting period. + 1. The initial height represents the starting height consensus states which will be copied from the substitute client to the frozen/expired client. + 1. If this governance proposal passes, the client on trial will be updated with all the state of the substitute, if and only if: 1. `allow_governance_override_after_expiry` is true and the client has expired (`Expired()` returns true) 1. `allow_governance_override_after_misbehaviour` is true and the client has been frozen (`Frozen()` returns true) 1. In this case, additionally, the client is unfrozen by calling `Unfreeze()` -Note additionally that the header submitted by governance must be new enough that it will be possible to update the light client after the new header is inserted into the client state (which will only happen after the governance proposal has passed). + +Note that clients frozen due to misbehaviour must wait for the evidence to expire to avoid becoming refrozen. This ADR does not address planned upgrades, which are handled separately as per the [specification](https://github.com/cosmos/ics/tree/master/spec/ics-007-tendermint-client#upgrades). @@ -58,11 +63,13 @@ This ADR does not address planned upgrades, which are handled separately as per - Establishes a mechanism for client recovery in the case of expiry - Establishes a mechanism for client recovery in the case of misbehaviour - Clients can elect to disallow this recovery mechanism if they do not wish to allow for it +- Constructing an ClientUpdate Proposal is as difficult as creating a new client ### Negative - Additional complexity in client creation which must be understood by the user -- Governance participants must pick a new header, which is a bit different from their usual tasks +- Coping state of the substitute adds complexity +- Governance participants must vote on a substitute client ### Neutral From afda62174fe6531b2a40c595a4d9396c28e8b391 Mon Sep 17 00:00:00 2001 From: Amaury Date: Mon, 18 Jan 2021 01:11:26 +0100 Subject: [PATCH 042/152] docs: Remove deprecated "Interfaces" section (#8294) * Remove useless files, add app.toml section * Rework docs * Delete interfaces * add correct next section references * Finish CLI * Small tweaks query * Add simulation docs to core * Add gRPC and REST * Finish queyr lifecycle * Updat examples * Remove prereq * fix links in simulation * Use same enumeration in md Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/basics/README.md | 5 +- docs/basics/accounts.md | 2 +- docs/basics/app-anatomy.md | 6 +- docs/basics/gas-fees.md | 2 +- docs/basics/query-lifecycle.md | 140 ++++++++++++ docs/building-modules/module-interfaces.md | 4 +- docs/core/README.md | 24 +- docs/core/cli.md | 125 +++++++++++ docs/core/events.md | 2 +- docs/core/grpc_rest.md | 14 +- docs/core/ocap.md | 2 +- docs/core/runtx_middleware.md | 8 +- docs/{using-the-sdk => core}/simulation.md | 72 +++--- docs/core/telemetry.md | 2 +- docs/interfaces/README.md | 14 -- docs/interfaces/cli.md | 136 ------------ docs/interfaces/interfaces-intro.md | 44 ---- docs/interfaces/lite/getting_started.md | 20 -- docs/interfaces/lite/pics/C2H.png | Bin 17324 -> 0 bytes docs/interfaces/lite/pics/H2C.png | Bin 20012 -> 0 bytes docs/interfaces/lite/pics/MA.png | Bin 31774 -> 0 bytes docs/interfaces/lite/pics/absence1.png | Bin 97697 -> 0 bytes docs/interfaces/lite/pics/absence2.png | Bin 31717 -> 0 bytes docs/interfaces/lite/pics/absence3.png | Bin 28517 -> 0 bytes docs/interfaces/lite/pics/architecture.png | Bin 30539 -> 0 bytes docs/interfaces/lite/pics/changeProcess.png | Bin 8919 -> 0 bytes .../interfaces/lite/pics/commitValidation.png | Bin 64713 -> 0 bytes docs/interfaces/lite/pics/create-account.png | Bin 21826 -> 0 bytes docs/interfaces/lite/pics/deposit.png | Bin 20738 -> 0 bytes docs/interfaces/lite/pics/existProof.png | Bin 96053 -> 0 bytes docs/interfaces/lite/pics/high-level.png | Bin 11595 -> 0 bytes .../lite/pics/light-client-architecture.png | Bin 24816 -> 0 bytes .../lite/pics/loadbalanceDiagram.png | Bin 34910 -> 0 bytes .../interfaces/lite/pics/simpleMerkleTree.png | Bin 24768 -> 0 bytes docs/interfaces/lite/pics/substoreProof.png | Bin 62165 -> 0 bytes docs/interfaces/lite/pics/transfer-tokens.png | Bin 26410 -> 0 bytes docs/interfaces/lite/pics/transfer.png | Bin 18492 -> 0 bytes docs/interfaces/lite/pics/trustPropagate.png | Bin 49750 -> 0 bytes .../lite/pics/updateValidatorToHeight.png | Bin 18077 -> 0 bytes .../lite/pics/validatorSetChange.png | Bin 36169 -> 0 bytes docs/interfaces/lite/pics/withdraw.png | Bin 20935 -> 0 bytes docs/interfaces/lite/readme.md | 91 -------- docs/interfaces/lite/specification.md | 209 ------------------ docs/interfaces/query-lifecycle.md | 162 -------------- docs/interfaces/rest.md | 70 ------ docs/run-node/interact-node.md | 8 +- docs/run-node/run-node.md | 6 + 47 files changed, 352 insertions(+), 816 deletions(-) create mode 100644 docs/basics/query-lifecycle.md create mode 100644 docs/core/cli.md rename docs/{using-the-sdk => core}/simulation.md (54%) delete mode 100644 docs/interfaces/README.md delete mode 100644 docs/interfaces/cli.md delete mode 100644 docs/interfaces/interfaces-intro.md delete mode 100644 docs/interfaces/lite/getting_started.md delete mode 100644 docs/interfaces/lite/pics/C2H.png delete mode 100644 docs/interfaces/lite/pics/H2C.png delete mode 100644 docs/interfaces/lite/pics/MA.png delete mode 100755 docs/interfaces/lite/pics/absence1.png delete mode 100755 docs/interfaces/lite/pics/absence2.png delete mode 100755 docs/interfaces/lite/pics/absence3.png delete mode 100644 docs/interfaces/lite/pics/architecture.png delete mode 100755 docs/interfaces/lite/pics/changeProcess.png delete mode 100755 docs/interfaces/lite/pics/commitValidation.png delete mode 100644 docs/interfaces/lite/pics/create-account.png delete mode 100644 docs/interfaces/lite/pics/deposit.png delete mode 100755 docs/interfaces/lite/pics/existProof.png delete mode 100644 docs/interfaces/lite/pics/high-level.png delete mode 100644 docs/interfaces/lite/pics/light-client-architecture.png delete mode 100644 docs/interfaces/lite/pics/loadbalanceDiagram.png delete mode 100755 docs/interfaces/lite/pics/simpleMerkleTree.png delete mode 100755 docs/interfaces/lite/pics/substoreProof.png delete mode 100644 docs/interfaces/lite/pics/transfer-tokens.png delete mode 100644 docs/interfaces/lite/pics/transfer.png delete mode 100755 docs/interfaces/lite/pics/trustPropagate.png delete mode 100755 docs/interfaces/lite/pics/updateValidatorToHeight.png delete mode 100755 docs/interfaces/lite/pics/validatorSetChange.png delete mode 100644 docs/interfaces/lite/pics/withdraw.png delete mode 100644 docs/interfaces/lite/readme.md delete mode 100644 docs/interfaces/lite/specification.md delete mode 100644 docs/interfaces/query-lifecycle.md delete mode 100644 docs/interfaces/rest.md diff --git a/docs/basics/README.md b/docs/basics/README.md index ad54c6bee783..03934dcd5112 100644 --- a/docs/basics/README.md +++ b/docs/basics/README.md @@ -10,7 +10,8 @@ This repository contains reference documentation on the basic concepts of the Co 1. [Anatomy of an SDK Application](./app-anatomy.md) 2. [Lifecycle of a transaction](./tx-lifecycle.md) -3. [Accounts](./accounts.md) -4. [Gas and Fees](./gas-fees.md) +3. [Lifecycle of a query](./query-lifecycle.md) +4. [Accounts](./accounts.md) +5. [Gas and Fees](./gas-fees.md) After reading the basics, head on to the [Core Reference](../core/README.md) for more advanced material. diff --git a/docs/basics/accounts.md b/docs/basics/accounts.md index 930914d73501..3b50c7a145b7 100644 --- a/docs/basics/accounts.md +++ b/docs/basics/accounts.md @@ -1,5 +1,5 @@ # Accounts diff --git a/docs/basics/app-anatomy.md b/docs/basics/app-anatomy.md index 148ba9ba5da4..225da66c3c29 100644 --- a/docs/basics/app-anatomy.md +++ b/docs/basics/app-anatomy.md @@ -120,7 +120,7 @@ Here are descriptions of what each of the four fields means: - `TxConfig`: `TxConfig` defines an interface a client can utilize to generate an application-defined concrete transaction type. Currently, the SDK handles two transaction types: `SIGN_MODE_DIRECT` (which uses Protobuf binary as over-the-wire encoding) and `SIGN_MODE_LEGACY_AMINO_JSON` (which depends on Amino). Read more about transactions [here](../core/transactions.md). - `Amino`: Some legacy parts of the SDK still use Amino for backwards-compatibility. Each module exposes a `RegisterLegacyAmino` method to register the module's specific types within Amino. This `Amino` codec should not be used by app developers anymore, and will be removed in future releases. -The SDK exposes a `MakeTestEncodingConfig` function used to create a `EncodingConfig` for the app constructor (`NewApp`). It uses Protobuf as a default `Marshaler`. +The SDK exposes a `MakeTestEncodingConfig` function used to create a `EncodingConfig` for the app constructor (`NewApp`). It uses Protobuf as a default `Marshaler`. NOTE: this function is marked deprecated and should only be used to create an app or in tests. We are working on refactoring codec management in a post Stargate release. See an example of a `MakeTestEncodingConfig` from `simapp`: @@ -160,7 +160,7 @@ Each module should also implement the `RegisterServices` method as part of the [ ### gRPC `Query` Services -gRPC `Query` services are introduced in the v0.40 Stargate release. They allow users to query the state using [gRPC](https://grpc.io). They are enabled by default, and can be configued under the `grpc.enable` and `grpc.address` fields inside `app.toml`. +gRPC `Query` services are introduced in the v0.40 Stargate release. They allow users to query the state using [gRPC](https://grpc.io). They are enabled by default, and can be configued under the `grpc.enable` and `grpc.address` fields inside [`app.toml`](../run-node/run-node.md#configuring-the-node-using-apptoml). gRPC `Query` services are defined in the module's Protobuf definition files, specifically inside `query.proto`. The `query.proto` definition file exposes a single `Query` [Protobuf service](https://developers.google.com/protocol-buffers/docs/proto#services). Each gRPC query endpoint corresponds to a service method, starting with the `rpc` keyword, inside the `Query` service. @@ -208,7 +208,7 @@ Some external clients may not wish to use gRPC. The SDK provides in this case a The REST endpoints are defined in the Protobuf files, along with the gRPC services, using Protobuf annotations. Modules that want to expose REST queries should add `google.api.http` annotations to their `rpc` methods. By default, all REST endpoints defined in the SDK have an URL starting with the `/cosmos/` prefix. -The SDK also provides a development endpoint to generate [Swagger](https://swagger.io/) definition files for these REST endpoints. This endpoint can be enabled inside the `app.toml` config file, under the `api.swagger` key. +The SDK also provides a development endpoint to generate [Swagger](https://swagger.io/) definition files for these REST endpoints. This endpoint can be enabled inside the [`app.toml`](../run-node/run-node.md#configuring-the-node-using-apptoml) config file, under the `api.swagger` key. #### Legacy API REST Endpoints diff --git a/docs/basics/gas-fees.md b/docs/basics/gas-fees.md index 270066996e72..2ab586497cd9 100644 --- a/docs/basics/gas-fees.md +++ b/docs/basics/gas-fees.md @@ -1,5 +1,5 @@ # Gas and Fees diff --git a/docs/basics/query-lifecycle.md b/docs/basics/query-lifecycle.md new file mode 100644 index 000000000000..4b4c509bb354 --- /dev/null +++ b/docs/basics/query-lifecycle.md @@ -0,0 +1,140 @@ + + +# Query Lifecycle + +This document describes the lifecycle of a query in a SDK application, from the user interface to application stores and back. {synopsis} + +## Pre-requisite Readings + +- [Transaction Lifecycle](./tx-lifecycle.md) {prereq} + +## Query Creation + +A [**query**](../building-modules/messages-and-queries.md#queries) is a request for information made by end-users of applications through an interface and processed by a full-node. Users can query information about the network, the application itself, and application state directly from the application's stores or modules. Note that queries are different from [transactions](../core/transactions.md) (view the lifecycle [here](./tx-lifecycle.md)), particularly in that they do not require consensus to be processed (as they do not trigger state-transitions); they can be fully handled by one full-node. + +For the purpose of explaining the query lifecycle, let's say `MyQuery` is requesting a list of delegations made by a certain delegator address in the application called `simapp`. As to be expected, the [`staking`](../../x/staking/spec/README.md) module handles this query. But first, there are a few ways `MyQuery` can be created by users. + +### CLI + +The main interface for an application is the command-line interface. Users connect to a full-node and run the CLI directly from their machines - the CLI interacts directly with the full-node. To create `MyQuery` from their terminal, users type the following command: + +```bash +simd query staking delegations +``` + +This query command was defined by the [`staking`](../../x/staking/spec/README.md) module developer and added to the list of subcommands by the application developer when creating the CLI. + +Note that the general format is as follows: + +```bash +simd query [moduleName] [command] --flag +``` + +To provide values such as `--node` (the full-node the CLI connects to), the user can use the [`app.toml`](../run-node/run-node.md#configuring-the-node-using-apptoml) config file to set them or provide them as flags. + +The CLI understands a specific set of commands, defined in a hierarchical structure by the application developer: from the [root command](../core/cli.md#root-command) (`simd`), the type of command (`Myquery`), the module that contains the command (`staking`), and command itself (`delegations`). Thus, the CLI knows exactly which module handles this command and directly passes the call there. + +### gRPC + +Another interface through which users can make queries, introduced in Cosmos SDK v0.40, is [gRPC](https://grpc.io) requests to a [gRPC server](../core/grpc_rest.md#grpc-server). The endpoints are defined as [Protocol Buffers](https://developers.google.com/protocol-buffers) service methods inside `.proto` files, written in Protobuf's own language-agnostic interface definition language (IDL). The Protobuf ecosystem developed tools for code-generation from `*.proto` files into various languages. These tools allow to build gRPC clients easily. + +One such tool is [grpcurl](https://github.com/fullstorydev/grpcurl), and a gRPC request for `MyQuery` using this client looks like: + +```bash +grpcurl \ + -plaintext # We want results in plain test + -import-path ./proto \ # Import these .proto files + -proto ./proto/cosmos/staking/v1beta1/query.proto \ # Look into this .proto file for the Query protobuf service + -d '{"address":"$MY_DELEGATOR"}' \ # Query arguments + localhost:9090 \ # gRPC server endpoint + cosmos.staking.v1beta1.Query/Delegations # Fully-qualified service method name +``` + +### REST + +Another interface through which users can make queries is through HTTP Requests to a [REST server](../core/grpc_rest.md#rest-server). The REST server is fully auto-generated from Protobuf services, using [gRPC-gateway](https://github.com/grpc-ecosystem/grpc-gateway). + +An example HTTP request for `MyQuery` looks like: + +```bash +GET http://localhost:1317/cosmos/staking/v1beta1/delegators/{delegatorAddr}/delegations +``` + +## How Queries are Handled by the CLI + +The examples above show how an external user can interact with a node by querying its state. To understand more in details the exact lifecycle of a query, let's dig into how the CLI prepares the query, and how the node handles it. The interactions from the users' perspective are a bit different, but the underlying functions are almost identical because they are implementations of the same command defined by the module developer. This step of processing happens within the CLI, gRPC or REST server and heavily involves a `client.Context`. + +### Context + +The first thing that is created in the execution of a CLI command is a `client.Context`. A `client.Context` is an object that stores all the data needed to process a request on the user side. In particular, a `client.Context` stores the following: + +- **Codec**: The [encoder/decoder](../core/encoding.md) used by the application, used to marshal the parameters and query before making the Tendermint RPC request and unmarshal the returned response into a JSON object. The default codec used by the CLI is Protobuf. +- **Account Decoder**: The account decoder from the [`auth`](../..//x/auth/spec/README.md) module, which translates `[]byte`s into accounts. +- **RPC Client**: The Tendermint RPC Client, or node, to which the request will be relayed to. +- **Keyring**: A [Key Manager](../basics/accounts.md#keyring) used to sign transactions and handle other operations with keys. +- **Output Writer**: A [Writer](https://golang.org/pkg/io/#Writer) used to output the response. +- **Configurations**: The flags configured by the user for this command, including `--height`, specifying the height of the blockchain to query and `--indent`, which indicates to add an indent to the JSON response. + +The `client.Context` also contains various functions such as `Query()` which retrieves the RPC Client and makes an ABCI call to relay a query to a full-node. + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/client/context.go#L20-L50 + +The `client.Context`'s primary role is to store data used during interactions with the end-user and provide methods to interact with this data - it is used before and after the query is processed by the full-node. Specifically, in handling `MyQuery`, the `client.Context` is utilized to encode the query parameters, retrieve the full-node, and write the output. Prior to being relayed to a full-node, the query needs to be encoded into a `[]byte` form, as full-nodes are application-agnostic and do not understand specific types. The full-node (RPC Client) itself is retrieved using the `client.Context`, which knows which node the user CLI is connected to. The query is relayed to this full-node to be processed. Finally, the `client.Context` contains a `Writer` to write output when the response is returned. These steps are further described in later sections. + +### Arguments and Route Creation + +At this point in the lifecycle, the user has created a CLI command with all of the data they wish to include in their query. A `client.Context` exists to assist in the rest of the `MyQuery`'s journey. Now, the next step is to parse the command or request, extract the arguments, and encode everything. These steps all happen on the user side within the interface they are interacting with. + +#### Encoding + +In our case (querying an address's delegations), `MyQuery` contains an [address](./accounts.md#addresses) `delegatorAddress` as its only argument. However, the request can only contain `[]byte`s, as it will be relayed to a consensus engine (e.g. Tendermint Core) of a full-node that has no inherent knowledge of the application types. Thus, the `codec` of `client.Context` is used to marshal the address. + +Here is what the code looks like for the CLI command: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/x/staking/client/cli/query.go#L324-L327 + +#### gRPC Query Client Creation + +The SDK leverages code generated from Protobuf services to make queries. The `staking` module's `MyQuery` service generates a `queryClient`, which the CLI will use to make queries. Here is the relevant code: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/x/staking/client/cli/query.go#L318-L342 + +Under the hood, the `client.Context` has a `Query()` function used to retrieve the pre-configured node and relay a query to it; the function takes the query fully-qualified service method name as path (in our case: `/cosmos.staking.v1beta1.Query/Delegations`), and arguments as parameters. It first retrieves the RPC Client (called the [**node**](../core/node.md)) configured by the user to relay this query to, and creates the `ABCIQueryOptions` (parameters formatted for the ABCI call). The node is then used to make the ABCI call, `ABCIQueryWithOptions()`. + +Here is what the code looks like: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/client/query.go#L65-L91 + +## RPC + +With a call to `ABCIQueryWithOptions()`, `MyQuery` is received by a [full-node](../core/encoding.md) which will then process the request. Note that, while the RPC is made to the consensus engine (e.g. Tendermint Core) of a full-node, queries are not part of consensus and will not be broadcasted to the rest of the network, as they do not require anything the network needs to agree upon. + +Read more about ABCI Clients and Tendermint RPC in the Tendermint documentation [here](https://tendermint.com/rpc). + +## Application Query Handling + +When a query is received by the full-node after it has been relayed from the underlying consensus engine, it is now being handled within an environment that understands application-specific types and has a copy of the state. [`baseapp`](../core/baseapp.md) implements the ABCI [`Query()`](../core/baseapp.md#query) function and handles gRPC queries. The query route is parsed, and it it matches the fully-qualified service method name of an existing service method (most likely in one of the modules), then `baseapp` will relay the request to the relevant module. + +Apart from gRPC routes, `baseapp` also handles four different types of queries: `app`, `store`, `p2p`, and `custom`. The first three types (`app`, `store`, `p2p`) are purely application-level and thus directly handled by `baseapp` or the stores, but the `custom` query type requires `baseapp` to route the query to a module's [legacy queriers](../building-modules/query-services.md#legacy-queriers). To learn more about these queries, please refer to [this guide](../core/grpc_rest.md#tendermint-rpc). + +Since `MyQuery` has a Protobuf fully-qualified service method name from the `staking` module (recall `/cosmos.staking.v1beta1.Query/Delegations`), `baseapp` first parses the path, then uses its own internal `GRPCQueryRouter` to retrieve the corresponding gRPC handler, and routes the query to the module. The gRPC handler is responsible for recognizing this query, retrieving the appropriate values from the application's stores, and returning a response. Read more about query services [here](../building-modules/query-services.md). + +Once a result is received from the querier, `baseapp` begins the process of returning a response to the user. + +## Response + +Since `Query()` is an ABCI function, `baseapp` returns the response as an [`abci.ResponseQuery`](https://tendermint.com/docs/spec/abci/abci.html#messages) type. The `client.Context` `Query()` routine receives the response and. + +### CLI Response + +The application [`codec`](../core/encoding.md) is used to unmarshal the response to a JSON and the `client.Context` prints the output to the command line, applying any configurations such as the output type (text, JSON or YAML). + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/client/context.go#L248-L283 + +And that's a wrap! The result of the query is outputted to the console by the CLI. + +## Next {hide} + +Read more about [accounts](./accounts.md). {hide} diff --git a/docs/building-modules/module-interfaces.md b/docs/building-modules/module-interfaces.md index 12c692cf52e5..0f811db4bf75 100644 --- a/docs/building-modules/module-interfaces.md +++ b/docs/building-modules/module-interfaces.md @@ -126,9 +126,9 @@ service Query{ } ``` -gRPC gateway is started in-process along with the application and Tendermint. It can be enabled or disabled by setting gRPC Configuration `enable` in `app.toml`. +gRPC gateway is started in-process along with the application and Tendermint. It can be enabled or disabled by setting gRPC Configuration `enable` in [`app.toml`](../run-node/run-node.md#configuring-the-node-using-apptoml). -The SDK provides a command for generating [Swagger](https://swagger.io/) documentation (`protoc-gen-swagger`). Setting `swagger` in `app.toml` defines if swagger documentation should be automatically registered. +The SDK provides a command for generating [Swagger](https://swagger.io/) documentation (`protoc-gen-swagger`). Setting `swagger` in [`app.toml`](../run-node/run-node.md#configuring-the-node-using-apptoml) defines if swagger documentation should be automatically registered. ## Legacy REST diff --git a/docs/core/README.md b/docs/core/README.md index 23df86d26909..94a993f5a556 100644 --- a/docs/core/README.md +++ b/docs/core/README.md @@ -9,17 +9,19 @@ parent: This repository contains reference documentation on the core concepts of the Cosmos SDK. 1. [`BaseApp`](./baseapp.md) -2. [Transaction](./transactions.md) -3. [Context](./context.md) -4. [Node Client](./node.md) -5. [Store](./store.md) -6. [Encoding](./encoding.md) -7. [gRPC, REST and Tendermint Endpoints](./grpc_rest.md) -8. [Events](./events.md) -9. [Telemetry](./telemetry.md) -10. [Object-Capabilities](./ocap.md) -11. [RunTx recovery middleware](./runtx_middleware.md) -12. [Protobuf documentation](./proto-docs.md) +1. [Transaction](./transactions.md) +1. [Context](./context.md) +1. [Node Client](./node.md) +1. [Store](./store.md) +1. [Encoding](./encoding.md) +1. [gRPC, REST and Tendermint Endpoints](./grpc_rest.md) +1. [Command-Line Interface](./cli.md) +1. [Events](./events.md) +1. [Telemetry](./telemetry.md) +1. [Object-Capabilities](./ocap.md) +1. [RunTx recovery middleware](./runtx_middleware.md) +1. [Simulation](./simulation.md) +1. [Protobuf documentation](./proto-docs.md) After reading about the core concepts, check the [IBC documentation](../ibc/README.md) to learn more about the IBC core concepts and how to integrate it to you application. diff --git a/docs/core/cli.md b/docs/core/cli.md new file mode 100644 index 000000000000..8e11bf488d2b --- /dev/null +++ b/docs/core/cli.md @@ -0,0 +1,125 @@ + + +# Command-Line Interface + +This document describes how commmand-line interface (CLI) works on a high-level, for an [**application**](../basics/app-anatomy.md). A separate document for implementing a CLI for an SDK [**module**](../building-modules/intro.md) can be found [here](../building-modules/module-interfaces.md#cli). {synopsis} + +## Command-Line Interface + +### Example Command + +There is no set way to create a CLI, but SDK modules typically use the [Cobra Library](https://github.com/spf13/cobra). Building a CLI with Cobra entails defining commands, arguments, and flags. [**Commands**](#commands) understand the actions users wish to take, such as `tx` for creating a transaction and `query` for querying the application. Each command can also have nested subcommands, necessary for naming the specific transaction type. Users also supply **Arguments**, such as account numbers to send coins to, and [**Flags**](#flags) to modify various aspects of the commands, such as gas prices or which node to broadcast to. + +Here is an example of a command a user might enter to interact with the simapp CLI `simd` in order to send some tokens: + +```bash +simd tx bank send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000stake --gas auto --gas-prices +``` + +The first four strings specify the command: + +- The root command for the entire application `simd`. +- The subcommand `tx`, which contains all commands that let users create transactions. +- The subcommand `bank` to indicate which module to route the command to ([`x/bank`](../../x/bank/spec/README.md) module in this case). +- The type of transaction `send`. + +The next two strings are arguments: the `from_address` the user wishes to send from, the `to_address` of the recipient, and the `amount` they want to send. Finally, the last few strings of the command are optional flags to indicate how much the user is willing to pay in fees (calculated using the amount of gas used to execute the transaction and the gas prices provided by the user). + +The CLI interacts with a [node](../core/node.md) to handle this command. The interface itself is defined in a `main.go` file. + +### Building the CLI + +The `main.go` file needs to have a `main()` function that creates a root command, to which all the application commands will be added as subcommands. The root command additionally handles: + +- **setting configurations** by reading in configuration files (e.g. the sdk config file). +- **adding any flags** to it, such as `--chain-id`. +- **instantiating the `codec`** by calling the application's `MakeCodec()` function (called `MakeTestEncodingConfig` in `simapp`). The [`codec`](../core/encoding.md) is used to encode and decode data structures for the application - stores can only persist `[]byte`s so the developer must define a serialization format for their data structures or use the default, Protobuf. +- **adding subcommand** for all the possible user interactions, including [transaction commands](#transaction-commands) and [query commands](#query-commands). + +The `main()` function finally creates an executor and [execute](https://godoc.org/github.com/spf13/cobra#Command.Execute) the root command. See an example of `main()` function from the `simapp` application: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/simapp/simd/main.go#L12-L24 + +The rest of the document will detail what needs to be implemented for each step and include smaller portions of code from the `simapp` CLI files. + +## Adding Commands to the CLI + +Every application CLI first constructs a root command, then adds functionality by aggregating subcommands (often with further nested subcommands) using `rootCmd.AddCommand()`. The bulk of an application's unique capabilities lies in its transaction and query commands, called `TxCmd` and `QueryCmd` respectively. + +### Root Command + +The root command (called `rootCmd`) is what the user first types into the command line to indicate which application they wish to interact with. The string used to invoke the command (the "Use" field) is typically the name of the application suffixed with `-d`, e.g. `simd` or `gaiad`. The root command typically includes the following commands to support basic functionality in the application. + +- **Status** command from the SDK rpc client tools, which prints information about the status of the connected [`Node`](../core/node.md). The Status of a node includes `NodeInfo`,`SyncInfo` and `ValidatorInfo`. +- **Keys** [commands](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/client/keys) from the SDK client tools, which includes a collection of subcommands for using the key functions in the SDK crypto tools, including adding a new key and saving it to the keyring, listing all public keys stored in the keyring, and deleting a key. For example, users can type `simd keys add ` to add a new key and save an encrypted copy to the keyring, using the flag `--recover` to recover a private key from a seed phrase or the flag `--multisig` to group multiple keys together to create a multisig key. For full details on the `add` key command, see the code [here](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/client/keys/add.go). For more details about usage of `--keyring-backend` for storage of key credentials look at the [keyring docs](../run-node/keyring.md). +- **Server** commands from the SDK server package. These commands are responsible for providing the mechanisms necessary to start an ABCI Tendermint application and provides the CLI framework (based on [cobra](github.com/spf13/cobra)) necessary to fully bootstrap an application. The package exposes two core functions: `StartCmd` and `ExportCmd` which creates commands to start the application and export state respectively. Click [here](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/server) to learn more. +- [**Transaction**](#transaction-commands) commands. +- [**Query**](#query-commands) commands. + +Next is an example `rootCmd` function from the `simapp` application. It instantiates the root command, adds a [_persistent_ flag](#flags) and `PreRun` function to be run before every execution, and adds all of the necessary subcommands. + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/simapp/simd/cmd/root.go#L37-L93 + +The root-level `status` and `keys` subcommands are common across most applications and do not interact with application state. The bulk of an application's functionality - what users can actually _do_ with it - is enabled by its `tx` and `query` commands. + +### Transaction Commands + +[Transactions](./transactions.md) are objects wrapping [`Msg`s](../building-modules/messages-and-queries.md#messages) that trigger state changes. To enable the creation of transactions using the CLI interface, a function `txCmd` is generally added to the `rootCmd`: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/simapp/simd/cmd/root.go#L86-L92 + +This `txCmd` function adds all the transaction available to end-users for the application. This typically includes: + +- **Sign command** from the [`auth`](../../x/auth/spec/README.md) module that signs messages in a transaction. To enable multisig, add the `auth` module's `MultiSign` command. Since every transaction requires some sort of signature in order to be valid, thithe signing command is necessary for every application. +- **Broadcast command** from the SDK client tools, to broadcast transactions. +- **All [module transaction commands](../building-modules/module-interfaces.md#transaction-commands)** the application is dependent on, retrieved by using the [basic module manager's](../building-modules/module-manager.md#basic-manager) `AddTxCommands()` function. + +Here is an example of a `txCmd` aggregating these subcommands from the `simapp` application: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/simapp/simd/cmd/root.go#L123-L149 + +### Query Commands + +[**Queries**](../building-modules/messages-and-queries.md#queries) are objects that allow users to retrieve information about the application's state. To enable the creation of transactions using the CLI interface, a function `txCmd` is generally added to the `rootCmd`: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/simapp/simd/cmd/root.go#L86-L92 + +This `queryCmd` function adds all the queries available to end-users for the application. This typically includes: + +- **QueryTx** and/or other transaction query commands] from the `auth` module which allow the user to search for a transaction by inputting its hash, a list of tags, or a block height. These queries allow users to see if transactions have been included in a block. +- **Account command** from the `auth` module, which displays the state (e.g. account balance) of an account given an address. +- **Validator command** from the SDK rpc client tools, which displays the validator set of a given height. +- **Block command** from the SDK rpc client tools, which displays the block data for a given height. +- **All [module query commands](../building-modules/module-interfaces.md#query-commands)** the application is dependent on, retrieved by using the [basic module manager's](../building-modules/module-manager.md#basic-manager) `AddQueryCommands()` function. + +Here is an example of a `queryCmd` aggregating subcommands from the `simapp` application: + ++++ https://github.com/cosmos/cosmos-sdk/blob/0.40.0/simapp/simd/cmd/root.go#L99-L121 + +## Flags + +Flags are used to modify commands; developers can include them in a `flags.go` file with their CLI. Users can explicitly include them in commands or pre-configure them by inside their [`app.toml`](../run-node/run-node.md#configuring-the-node-using-apptoml). Commonly pre-configured flags include the `--node` to connect to and `--chain-id` of the blockchain the user wishes to interact with. + +A _persistent_ flag (as opposed to a _local_ flag) added to a command transcends all of its children: subcommands will inherit the configured values for these flags. Additionally, all flags have default values when they are added to commands; some toggle an option off but others are empty values that the user needs to override to create valid commands. A flag can be explicitly marked as _required_ so that an error is automatically thrown if the user does not provide a value, but it is also acceptable to handle unexpected missing flags differently. + +Flags are added to commands directly (generally in the [module's CLI file](../building-modules/module-interfaces.md#flags) where module commands are defined) and no flag except for the `rootCmd` persistent flags has to be added at application level. It is common to add a _persistent_ flag for `--chain-id`, the unique identifier of the blockchain the application pertains to, to the root command. Adding this flag can be done in the `main()` function. Adding this flag makes sense as the chain ID should not be changing across commands in this application CLI. Here is an example from the `simapp` application: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/simapp/simd/cmd/root.go#L118 + +## Configurations + +It is vital that the root command of an application uses `PersistentPreRun()` cobra command property for executing the command, so all child commands have access to the server and client contexts. These contexts are set as their default values initially and maybe modified, scoped to the command, in their respective `PersistentPreRun()` functions. Note that the `client.Context` is typically pre-populated with "default" values that may be useful for all commands to inherit and override if necessary. + +Here is an example of an `PersistentPreRun()` function from `simapp``: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/simapp/simd/cmd/root.go#L54-L60 + +The `SetCmdClientContextHandler` call reads persistent flags via `ReadPersistentCommandFlags` which creates a `client.Context` and sets that on the root command's `Context`. + +The `InterceptConfigsPreRunHandler` call creates a viper literal, default `server.Context`, and a logger and sets that on the root command's `Context`. The `server.Context` will be modified and saved to disk via the internal `interceptConfigs` call, which either reads or creates a Tendermint configuration based on the home path provided. In addition, `interceptConfigs` also reads and loads the application configuration, `app.toml`, and binds that to the `server.Context` viper literal. This is vital so the application can get access to not only the CLI flags, but also to the application configuration values provided by this file. + +## Next {hide} + +Learn about [events](./events.md) {hide} diff --git a/docs/core/events.md b/docs/core/events.md index bffa432ba4bc..87bf87066133 100644 --- a/docs/core/events.md +++ b/docs/core/events.md @@ -1,5 +1,5 @@ # Events diff --git a/docs/core/grpc_rest.md b/docs/core/grpc_rest.md index e89b0653ad2a..c78da2d94e48 100644 --- a/docs/core/grpc_rest.md +++ b/docs/core/grpc_rest.md @@ -26,13 +26,13 @@ Each module exposes [`Msg` and `Query` Protobuf services](../building-modules/me https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc4/server/types/app.go#L39-L41 -The `grpc.Server` is a concrete gRPC server, which spawns and serves any gRPC requests. This server can be configured inside `$TMHOME/config/app.toml`: +The `grpc.Server` is a concrete gRPC server, which spawns and serves any gRPC requests. This server can be configured inside `~/.simapp/config/app.toml`: - `grpc.enable = true|false` field defines if the gRPC server should be enabled. Defaults to `true`. - `grpc.address = {string}` field defines the address (really, the port, since the host should be kept at `0.0.0.0`) the server should bind to. Defaults to `0.0.0.0:9000`. ::tip -`$TMHOME` is the directory where the node's configuration and databases are stored. By default, it's set to `~/.{app_name}`. +`~/.simapp` is the directory where the node's configuration and databases are stored. By default, it's set to `~/.{app_name}`. :: Once the gRPC server is started, you can send requests to it using a gRPC client. Some examples are given in our [Interact with the Node](../run-node/interact-node.md#using-grpc) tutorial. @@ -43,11 +43,11 @@ An overview of all available gRPC endpoints shipped with the Cosmos SDK is [Prot In Cosmos SDK v0.40, the node continues to serve a REST server. However, the existing routes present in version v0.39 and earlier are now marked as deprecated, and new routes have been added via gRPC-gateway. -All routes are configured under the following fields in `$TMHOME/config/app.toml`: +All routes are configured under the following fields in `~/.simapp/config/app.toml`: - `api.enable = true|false` field defines if the REST server should be enabled. Defaults to `true`. - `api.address = {string}` field defines the address (really, the port, since the host should be kept at `0.0.0.0`) the server should bind to. Defaults to `tcp://0.0.0.0:1317`. -- some additional API configuration options are defined in `$TMHOME/config/app.toml`, along with comments, please refer to that file directly. +- some additional API configuration options are defined in `~/.simapp/config/app.toml`, along with comments, please refer to that file directly. ### gRPC-gateway REST Routes @@ -69,13 +69,13 @@ For application developers, Legacy REST API routes needs to be wired up to the R A [Swagger](https://swagger.io/) (or OpenAPIv2) specification file is exposed under the `/swagger` route on the API server. Swagger is an open specification describing the API endpoints a server serves, including description, input arguments, return types and much more about each endpoint. -Enabling the `/swagger` endpoint is configurable inside `$TMHOME/config/app.toml` via the `api.swagger` field, which is set to true by default. +Enabling the `/swagger` endpoint is configurable inside `~/.simapp/config/app.toml` via the `api.swagger` field, which is set to true by default. For application developers, you may want to generate your own Swagger definitions based on your custom modules. The SDK's [Swagger generation script](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc4/scripts/protoc-swagger-gen.sh) is a good place to start. ## Tendermint RPC -Independently from the Cosmos SDK, Tendermint also exposes a RPC server. This RPC server can be configured by tuning parameters under the `rpc` table in the `$TMHOME/config/config.toml`, the default listening address is `tcp://0.0.0.0:26657`. An OpenAPI specification of all Tendermint RPC endpoints is available [here](https://docs.tendermint.com/master/rpc/). +Independently from the Cosmos SDK, Tendermint also exposes a RPC server. This RPC server can be configured by tuning parameters under the `rpc` table in the `~/.simapp/config/config.toml`, the default listening address is `tcp://0.0.0.0:26657`. An OpenAPI specification of all Tendermint RPC endpoints is available [here](https://docs.tendermint.com/master/rpc/). Some Tendermint RPC endpoints are directly related to the Cosmos SDK: @@ -98,4 +98,4 @@ Some Tendermint RPC endpoints are directly related to the Cosmos SDK: ## Next {hide} -Learn about [events](./events.md) {hide} +Learn about [the CLI](./cli.md) {hide} diff --git a/docs/core/ocap.md b/docs/core/ocap.md index 523595c32479..3f0ec2e1d7ec 100644 --- a/docs/core/ocap.md +++ b/docs/core/ocap.md @@ -1,5 +1,5 @@ # Object-Capability Model diff --git a/docs/core/runtx_middleware.md b/docs/core/runtx_middleware.md index 8d205ca284fe..9c978fbbe00b 100644 --- a/docs/core/runtx_middleware.md +++ b/docs/core/runtx_middleware.md @@ -1,5 +1,5 @@ # RunTx recovery middleware @@ -22,12 +22,12 @@ type RecoveryHandler func(recoveryObj interface{}) error **Contract:** -* RecoveryHandler returns `nil` if `recoveryObj` wasn't handled and should be passed to the next recovery middleware; -* RecoveryHandler returns a non-nil `error` if `recoveryObj` was handled; +- RecoveryHandler returns `nil` if `recoveryObj` wasn't handled and should be passed to the next recovery middleware; +- RecoveryHandler returns a non-nil `error` if `recoveryObj` was handled; ## Custom RecoveryHandler register -``BaseApp.AddRunTxRecoveryHandler(handlers ...RecoveryHandler)`` +`BaseApp.AddRunTxRecoveryHandler(handlers ...RecoveryHandler)` BaseApp method adds recovery middleware to the default recovery chain. diff --git a/docs/using-the-sdk/simulation.md b/docs/core/simulation.md similarity index 54% rename from docs/using-the-sdk/simulation.md rename to docs/core/simulation.md index e8fcb8088f07..9b838b40b526 100644 --- a/docs/using-the-sdk/simulation.md +++ b/docs/core/simulation.md @@ -1,10 +1,14 @@ + + # Cosmos Blockchain Simulator The Cosmos SDK offers a full fledged simulation framework to fuzz test every message defined by a module. -On the SDK, this functionality is provided by the[`SimApp`](https://github.com/cosmos/cosmos-sdk/blob/master/simapp/app.go), which is a -`Baseapp` application that is used for running the [`simulation`](https://github.com/cosmos/cosmos-sdk/tree/master/x/simulation) module. +On the SDK, this functionality is provided by the[`SimApp`](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/simapp/app.go), which is a +`Baseapp` application that is used for running the [`simulation`](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/x/simulation) module. This module defines all the simulation logic as well as the operations for randomized parameters like accounts, balances etc. @@ -26,30 +30,30 @@ provided operations (randomized or not). The simulation app has different commands, each of which tests a different failure type: -* `AppImportExport`: The simulator exports the initial app state and then it -creates a new app with the exported `genesis.json` as an input, checking for -inconsistencies between the stores. -* `AppSimulationAfterImport`: Queues two simulations together. The first one provides the app state (_i.e_ genesis) to the second. Useful to test software upgrades or hard-forks from a live chain. -* `AppStateDeterminism`: Checks that all the nodes return the same values, in the same order. -* `BenchmarkInvariants`: Analysis of the performance of running all modules' invariants (_i.e_ sequentially runs a [benchmark](https://golang.org/pkg/testing/#hdr-Benchmarks) test). An invariant checks for -differences between the values that are on the store and the passive tracker. Eg: total coins held by accounts vs total supply tracker. -* `FullAppSimulation`: General simulation mode. Runs the chain and the specified operations for a given number of blocks. Tests that there're no `panics` on the simulation. It does also run invariant checks on every `Period` but they are not benchmarked. +- `AppImportExport`: The simulator exports the initial app state and then it + creates a new app with the exported `genesis.json` as an input, checking for + inconsistencies between the stores. +- `AppSimulationAfterImport`: Queues two simulations together. The first one provides the app state (_i.e_ genesis) to the second. Useful to test software upgrades or hard-forks from a live chain. +- `AppStateDeterminism`: Checks that all the nodes return the same values, in the same order. +- `BenchmarkInvariants`: Analysis of the performance of running all modules' invariants (_i.e_ sequentially runs a [benchmark](https://golang.org/pkg/testing/#hdr-Benchmarks) test). An invariant checks for + differences between the values that are on the store and the passive tracker. Eg: total coins held by accounts vs total supply tracker. +- `FullAppSimulation`: General simulation mode. Runs the chain and the specified operations for a given number of blocks. Tests that there're no `panics` on the simulation. It does also run invariant checks on every `Period` but they are not benchmarked. Each simulation must receive a set of inputs (_i.e_ flags) such as the number of blocks that the simulation is run, seed, block size, etc. -Check the full list of flags [here](https://github.com/cosmos/cosmos-sdk/blob/adf6ddd4a807c8363e33083a3281f6a5e112ab89/simapp/sim_test.go#L34-L50). +Check the full list of flags [here](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/simapp/config.go#L32-L55). ## Simulator Modes In addition to the various inputs and commands, the simulator runs in three modes: 1. Completely random where the initial state, module parameters and simulation -parameters are **pseudo-randomly generated**. + parameters are **pseudo-randomly generated**. 2. From a `genesis.json` file where the initial state and the module parameters are defined. -This mode is helpful for running simulations on a known state such as a live network export where a new (mostly likely breaking) version of the application needs to be tested. + This mode is helpful for running simulations on a known state such as a live network export where a new (mostly likely breaking) version of the application needs to be tested. 3. From a `params.json` file where the initial state is pseudo-randomly generated but the module and simulation parameters can be provided manually. -This allows for a more controlled and deterministic simulation setup while allowing the state space to still be pseudo-randomly simulated. -The list of available parameters are listed [here](https://github.com/cosmos/cosmos-sdk/blob/adf6ddd4a807c8363e33083a3281f6a5e112ab89/x/simulation/params.go#L170-L178). + This allows for a more controlled and deterministic simulation setup while allowing the state space to still be pseudo-randomly simulated. + The list of available parameters are listed [here](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/x/simulation/params.go#L44-L52). ::: tip These modes are not mutually exclusive. So you can for example run a randomly @@ -59,7 +63,7 @@ generated genesis state (`1`) with manually generated simulation params (`3`). ## Usage This is a general example of how simulations are run. For more specific examples -check the SDK [Makefile](https://github.com/cosmos/cosmos-sdk/blob/adf6ddd4a807c8363e33083a3281f6a5e112ab89/Makefile#L88-L123). +check the SDK [Makefile](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/Makefile#L251-L287). ```bash $ go test -mod=readonly github.com/cosmos/cosmos-sdk/simapp \ @@ -72,26 +76,26 @@ check the SDK [Makefile](https://github.com/cosmos/cosmos-sdk/blob/adf6ddd4a807c Here are some suggestions when encountering a simulation failure: -* Export the app state at the height were the failure was found. You can do this -by passing the `-ExportStatePath` flag to the simulator. -* Use `-Verbose` logs. They could give you a better hint on all the operations -involved. -* Reduce the simulation `-Period`. This will run the invariants checks more -frequently. -* Print all the failed invariants at once with `-PrintAllInvariants`. -* Try using another `-Seed`. If it can reproduce the same error and if it fails -sooner you will spend less time running the simulations. -* Reduce the `-NumBlocks` . How's the app state at the height previous to the -failure? -* Run invariants on every operation with `-SimulateEveryOperation`. _Note_: this -will slow down your simulation **a lot**. -* Try adding logs to operations that are not logged. You will have to define a -[Logger](https://github.com/cosmos/cosmos-sdk/blob/adf6ddd4a807c8363e33083a3281f6a5e112ab89/x/staking/keeper/keeper.go#L65:17) on your `Keeper`. +- Export the app state at the height were the failure was found. You can do this + by passing the `-ExportStatePath` flag to the simulator. +- Use `-Verbose` logs. They could give you a better hint on all the operations + involved. +- Reduce the simulation `-Period`. This will run the invariants checks more + frequently. +- Print all the failed invariants at once with `-PrintAllInvariants`. +- Try using another `-Seed`. If it can reproduce the same error and if it fails + sooner you will spend less time running the simulations. +- Reduce the `-NumBlocks` . How's the app state at the height previous to the + failure? +- Run invariants on every operation with `-SimulateEveryOperation`. _Note_: this + will slow down your simulation **a lot**. +- Try adding logs to operations that are not logged. You will have to define a + [Logger](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/x/staking/keeper/keeper.go#L66-L69) on your `Keeper`. ## Use simulation in your SDK-based application Learn how you can integrate the simulation into your SDK-based application: -* Application Simulation Manager -* [Building modules: Simulator](../building-modules/simulator.md) -* Simulator tests +- Application Simulation Manager +- [Building modules: Simulator](../building-modules/simulator.md) +- Simulator tests diff --git a/docs/core/telemetry.md b/docs/core/telemetry.md index b536fb480dff..9e434eef2bec 100644 --- a/docs/core/telemetry.md +++ b/docs/core/telemetry.md @@ -1,5 +1,5 @@ # Telemetry diff --git a/docs/interfaces/README.md b/docs/interfaces/README.md deleted file mode 100644 index f7fc2cd6e29f..000000000000 --- a/docs/interfaces/README.md +++ /dev/null @@ -1,14 +0,0 @@ - - -# Interfaces (Deprecated) - -This repository contains documentation on interfaces for Cosmos SDK applications. - -1. [Introduction to Interaces](./interfaces-intro.md) -2. [Lifecycle of a Query](./query-lifecycle.md) -3. [Command-Line Interface](./cli.md) -4. [Rest Interface](./rest.md) diff --git a/docs/interfaces/cli.md b/docs/interfaces/cli.md deleted file mode 100644 index d447abe82f17..000000000000 --- a/docs/interfaces/cli.md +++ /dev/null @@ -1,136 +0,0 @@ - - -# Command-Line Interface - -This document describes how to create a commmand-line interface (CLI) for an [**application**](../basics/app-anatomy.md). A separate document for implementing a CLI for an SDK [**module**](../building-modules/intro.md) can be found [here](#../building-modules/module-interfaces.md#cli). {synopsis} - -## Pre-requisite Readings - -* [Lifecycle of a Query](./query-lifecycle.md) {prereq} - -## Command-Line Interface - -One of the main entrypoints of an application is the command-line interface. This entrypoint is created via a `main.go` file which compiles to a binary, conventionally placed in the application's `./cmd/cli` folder. The CLI for an application is typically be referred to as the name of the application suffixed with `-cli`, e.g. `appcli`. Here is where the interfaces docs lie in the directory from the [nameservice tutorial](https://cosmos.network/docs/tutorial). - -### Example Command - -There is no set way to create a CLI, but SDK modules typically use the [Cobra Library](https://github.com/spf13/cobra). Building a CLI with Cobra entails defining commands, arguments, and flags. [**Commands**](#commands) understand the actions users wish to take, such as `tx` for creating a transaction and `query` for querying the application. Each command can also have nested subcommands, necessary for naming the specific transaction type. Users also supply **Arguments**, such as account numbers to send coins to, and [**Flags**](#flags) to modify various aspects of the commands, such as gas prices or which node to broadcast to. - -Here is an example of a command a user might enter to interact with the nameservice CLI `nscli` in order to buy a name: - -```bash -nscli tx nameservice buy-name --gas auto --gas-prices -``` - -The first four strings specify the command: - -- The root command for the entire application `nscli`. -- The subcommand `tx`, which contains all commands that let users create transactions. -- The subcommand `nameservice` to indicate which module to route the command to (`nameservice` module in this case). -- The type of transaction `buy-name`. - -The next two strings are arguments: the `name` the user wishes to buy and the `amount` they want to pay for it. Finally, the last few strings of the command are flags to indicate how much the user is willing to pay in fees (calculated using the amount of gas used to execute the transaction and the gas prices provided by the user). - -The CLI interacts with a [node](../core/node.md) (running `nsd`) to handle this command. The interface itself is defined in a `main.go` file. - -### Building the CLI - -The `main.go` file needs to have a `main()` function that does the following to run the command-line interface: - -* **Instantiate the `codec`** by calling the application's `MakeCodec()` function. The [`codec`](../core/encoding.md) is used to code and encode data structures for the application - stores can only persist `[]byte`s so the developer must define a serialization format for their data structures or use the default, [Amino](../core/encoding.md#amino). -* **Configurations** are set by reading in configuration files (e.g. the sdk config file). -* **Create the root command** to which all the application commands will be added as subcommands and add any required flags to it, such as `--chain-id`. -* **Add subcommands** for all the possible user interactions, including [transaction commands](#transaction-commands) and [query commands](#query-commands). -* **Create an Executor** and [execute](https://godoc.org/github.com/spf13/cobra#Command.Execute) the root command. - -See an example of `main()` function from the `nameservice` application: - -+++ https://github.com/cosmos/sdk-tutorials/blob/86a27321cf89cc637581762e953d0c07f8c78ece/nameservice/cmd/nscli/main.go#L23-L66 - -The rest of the document will detail what needs to be implemented for each step and include smaller portions of code from the nameservice CLI `main.go` file. - -## Adding Commands to the CLI - -Every application CLI first constructs a root command, then adds functionality by aggregating subcommands (often with further nested subcommands) using `rootCmd.AddCommand()`. The bulk of an application's unique capabilities lies in its transaction and query commands, called `TxCmd` and `QueryCmd` respectively. - -### Root Command - -The root command (called `rootCmd`) is what the user first types into the command line to indicate which application they wish to interact with. The string used to invoke the command (the "Use" field) is typically the name of the application suffixed with `-cli`, e.g. `appcli`. The root command typically includes the following commands to support basic functionality in the application. - -* **Status** command from the SDK rpc client tools, which prints information about the status of the connected [`Node`](../core/node.md). The Status of a node includes `NodeInfo`,`SyncInfo` and `ValidatorInfo`. -* **Config** [command](https://github.com/cosmos/cosmos-sdk/blob/master/client/config.go) from the SDK client tools, which allows the user to edit a `config.toml` file that sets values for [flags](#flags) such as `--chain-id` and which `--node` they wish to connect to. -The `config` command can be invoked by typing `appcli config` with optional arguments ` [value]` and a `--get` flag to query configurations or `--home` flag to create a new configuration. -* **Keys** [commands](https://github.com/cosmos/cosmos-sdk/blob/master/client/keys) from the SDK client tools, which includes a collection of subcommands for using the key functions in the SDK crypto tools, including adding a new key and saving it to disk, listing all public keys stored in the key manager, and deleting a key. For example, users can type `appcli keys add ` to add a new key and save an encrypted copy to disk, using the flag `--recover` to recover a private key from a seed phrase or the flag `--multisig` to group multiple keys together to create a multisig key. For full details on the `add` key command, see the code [here](https://github.com/cosmos/cosmos-sdk/blob/master/client/keys/add.go). For more details about usage of `--keyring-backend` for storage of key credentials look at the [keyring docs](/keyring.md). -* [**Transaction**](#transaction-commands) commands. -* [**Query**](#query-commands) commands. - -Next is an example `main()` function from the `nameservice` application. It instantiates the root command, adds a [*persistent* flag](#flags) and `PreRun` function to be run before every execution, and adds all of the necessary subcommands. - -+++ https://github.com/cosmos/sdk-tutorials/blob/86a27321cf89cc637581762e953d0c07f8c78ece/nameservice/cmd/nscli/main.go#L23-L66 - -The root-level `status`, `config`, and `keys` subcommands are common across most applications and do not interact with application state. The bulk of an application's functionality - what users can actually *do* with it - is enabled by its transaction commands. - -### Transaction Commands - -[Transactions](#./transactions.md) are objects wrapping [messages](../building-modules/messages-and-queries.md#messages) that trigger state changes. To enable the creation of transactions using the CLI interface, a function `txCmd` is generally added to the `rootCmd`: - -+++ https://github.com/cosmos/sdk-tutorials/blob/86a27321cf89cc637581762e953d0c07f8c78ece/nameservice/cmd/nscli/main.go#L51 - -This `txCmd` function adds all the transaction available to end-users for the application. This typically includes: - -* **Sign command** from the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/master/x/auth/spec) module that signs messages in a transaction. To enable multisig, add the `auth` module's `MultiSign` command. Since every transaction requires some sort of signature in order to be valid, thithe signing command is necessary for every application. -* **Broadcast command** from the SDK client tools, to broadcast transactions. -* **Send command** from the [`bank`](https://github.com/cosmos/cosmos-sdk/tree/master/x/bank/spec) module, which is a transaction that allows accounts to send coins to one another, including gas and fees for transactions. -* **All [module transaction commands](../building-modules/module-interfaces.md#transaction-commands)** the application is dependent on, retrieved by using the [basic module manager's](../building-modules/module-manager.md#basic-manager) `AddTxCommands()` function. - -Here is an example of a `txCmd` aggregating these subcommands from the `nameservice` application: - -+++ https://github.com/cosmos/sdk-tutorials/blob/86a27321cf89cc637581762e953d0c07f8c78ece/nameservice/cmd/nscli/main.go#L97-L118 - - -### Query Commands - -[**Queries**](../building-modules/messages-and-queries.md#queries) are objects that allow users to retrieve information about the application's state. To enable the creation of transactions using the CLI interface, a function `txCmd` is generally added to the `rootCmd`: - -+++ https://github.com/cosmos/sdk-tutorials/blob/86a27321cf89cc637581762e953d0c07f8c78ece/nameservice/cmd/nscli/main.go#L50 - -This `queryCmd` function adds all the queries available to end-users for the application. This typically includes: - -* **QueryTx** and/or other transaction query commands] from the `auth` module which allow the user to search for a transaction by inputting its hash, a list of tags, or a block height. These queries allow users to see if transactions have been included in a block. -* **Account command** from the `auth` module, which displays the state (e.g. account balance) of an account given an address. -* **Validator command** from the SDK rpc client tools, which displays the validator set of a given height. -* **Block command** from the SDK rpc client tools, which displays the block data for a given height. -* **All [module query commands](../building-modules/module-interfaces.md#query-commands)** the application is dependent on, retrieved by using the [basic module manager's](../building-modules/module-manager.md#basic-manager) `AddQueryCommands()` function. - -Here is an example of a `queryCmd` aggregating subcommands from the `nameservice` application: - -+++ https://github.com/cosmos/sdk-tutorials/blob/86a27321cf89cc637581762e953d0c07f8c78ece/nameservice/cmd/nscli/main.go#L74-L95 - -## Flags - -Flags are used to modify commands; developers can include them in a `flags.go` file with their CLI. Users can explicitly include them in commands or pre-configure them by entering a command in the format `appcli config ` into their command line. Commonly pre-configured flags include the `--node` to connect to and `--chain-id` of the blockchain the user wishes to interact with. - -A *persistent* flag (as opposed to a _local_ flag) added to a command transcends all of its children: subcommands will inherit the configured values for these flags. Additionally, all flags have default values when they are added to commands; some toggle an option off but others are empty values that the user needs to override to create valid commands. A flag can be explicitly marked as _required_ so that an error is automatically thrown if the user does not provide a value, but it is also acceptable to handle unexpected missing flags differently. - -Flags are added to commands directly (generally in the [module's CLI file](../building-modules/module-interfaces.md#flags) where module commands are defined) and no flag except for the `rootCmd` persistent flags has to be added at application level. It is common to add a _persistent_ flag for `--chain-id`, the unique identifier of the blockchain the application pertains to, to the root command. Adding this flag can be done in the `main()` function. Adding this flag makes sense as the chain ID should not be changing across commands in this application CLI. Here is an example from the `nameservice` application: - -+++ https://github.com/cosmos/sdk-tutorials/blob/86a27321cf89cc637581762e953d0c07f8c78ece/nameservice/cmd/nscli/main.go#L41 - - -## Configurations - -The last function to define in `main.go` is `initConfig`, which does exactly what it sounds like - initialize configurations. To call this function, set it as a `PersistentPreRunE` function for the root command, so that it always executes before the main execution of the root command and any of its subcommands. `initConfig()` does the following: - -1. Read in the `config.toml` file. This same file is edited through `config` commands. -2. Use the [Viper](https://github.com/spf13/viper) to read in configurations from the file and set them. -3. Set any persistent flags defined by the user: `--chain-id`, `--encoding`, `--output`, etc. - -Here is an example of an `initConfig()` function from the [nameservice tutorial CLI](https://cosmos.network/docs/tutorial/entrypoint.html#nscli): - -+++ https://github.com/cosmos/sdk-tutorials/blob/86a27321cf89cc637581762e953d0c07f8c78ece/nameservice/cmd/nscli/main.go#L120-L141 - -And an example of how to add `initConfig` as a `PersistentPreRunE` to the root command: - -+++ https://github.com/cosmos/sdk-tutorials/blob/86a27321cf89cc637581762e953d0c07f8c78ece/nameservice/cmd/nscli/main.go#L42-L44 diff --git a/docs/interfaces/interfaces-intro.md b/docs/interfaces/interfaces-intro.md deleted file mode 100644 index fa2c8bf8d496..000000000000 --- a/docs/interfaces/interfaces-intro.md +++ /dev/null @@ -1,44 +0,0 @@ - - -# Interfaces - -Typically, SDK applications include interfaces to let end-users interact with the application. This document introduces the different types of interfaces for SDK applications. {synopsis} - -## Pre-requisite Readings - -* [Anatomy of an SDK Application](../basics/app-anatomy.md) {prereq} -* [Lifecycle of a Transaction](../basics/tx-lifecycle.md) {prereq} - -## Types of Application Interfaces - -SDK applications generally have a Command-Line Interface (CLI) and REST Interface to support interactions with a [full-node](../core/node.md). The SDK is opinionated about how to create these two interfaces; all modules specify [Cobra commands](https://github.com/spf13/cobra) and register routes using [Gorilla Mux routers](https://github.com/gorilla/mux). The CLI and REST Interface are conventionally defined in the application `./app/cmd/cli` folder. - -## Module vs Application Interfaces - -The process of creating an application interface is distinct from creating a [module interface](../building-modules/module-interfaces.md), though the two are closely intertwined. As expected, module interfaces handle the bulk of the underlying logic, defining ways for end-users to create [messages](../building-modules/messages-and-queries.md#messages) and [queries](../building-modules/messages-and-queries.md#queries) to the subset of application state within their scope. On the other hand, application interfaces aggregate module-level interfaces in order to route `messages` and `queries` to the appropriate modules. Application interfaces also handle root-level responsibilities such as signing and broadcasting [transactions](../core/transactions.md) that wrap messages. - -### Module Developer Responsibilities - -With regards to interfaces, module developers need to include the following definitions: - -* **CLI commands:** Specifically, [Transaction commands](../building-modules/module-interfaces.md#transaction-commands) and [Query commands](../building-modules/module-interfaces.md#query-commands). These are commands that users will invoke when interacting with the application to create transactions and queries. For example, if an application enables sending coins through the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/master/x/auth/spec) module, users will create `tx auth send` transactions. -* **Request Handlers:** Also categorized into Transaction and Query requests. Transactions will require HTTP [Request Types](../building-modules/module-interfaces.md#request-types) in addition to [Request Handlers](../building-modules/module-interfaces.md#request-handlers) in order to encapsulate all of the user's options (e.g. gas prices). -* **REST Routes:** Given a router, the module interface registers paths with the aforementioned [Request Handlers](../building-modules/module-interfaces.md#request-handlers) for each type of request. - -Module interfaces are designed to be generic. Both commands and request types include required user input (through flags or request body) which are different for each application. This section of documents will only detail application interfaces; to read about how to build module interfaces, click [here](../building-modules/module-interfaces.md). - -### Application Developer Responsibilities - -With regards to interfaces, application developers need to include: - -* **CLI Root Command:** The [root command](./cli.md#root-command) adds subcommands to include all of the functionality for the application, mainly module [transaction](./cli.md#transaction-commands) and [query](./cli.md#query-commands) commands from the application's module(s). -* **App Configurations:** All application-specific values are the responsibility of the application developer, including the [`codec`](../core/encoding.md) used to marshal requests before relaying them to a node. -* **User Configurations:** Some values are specific to the user, such as the user's address and which node they are connected to. The CLI has a [configurations](./cli.md#configurations) function to set these values. -* **RegisterRoutes Function:** [Routes](./rest.md#registerroutes) must be registered and passed to an instantiated [REST server](./rest.md#rest-server) so that it knows how to route requests for this particular application. - - -## Next {hide} - -Read about the [Lifecycle of a Query](./query-lifecycle.md) {hide} diff --git a/docs/interfaces/lite/getting_started.md b/docs/interfaces/lite/getting_started.md deleted file mode 100644 index 23c92821b4e3..000000000000 --- a/docs/interfaces/lite/getting_started.md +++ /dev/null @@ -1,20 +0,0 @@ -# Getting Started - -To start a REST server, we need to specify the following parameters: - -| Parameter | Type | Default | Required | Description | -| ----------- | --------- | ----------------------- | -------- | ---------------------------------------------------- | -| chain-id | string | null | true | chain id of the full node to connect | -| node | URL | "tcp://localhost:46657" | true | address of the full node to connect | -| laddr | URL | "tcp://localhost:1317" | true | address to run the rest server on | -| trust-store | DIRECTORY | "$HOME/.lcd" | false | directory for save checkpoints and validator sets | - -For example: - -```bash -gaiacli rest-server --chain-id=test \ - --laddr=tcp://localhost:1317 \ - --node tcp://localhost:26657 \ -``` - -For more information about the Gaia-Lite RPC, see the [swagger documentation](https://cosmos.network/rpc/) diff --git a/docs/interfaces/lite/pics/C2H.png b/docs/interfaces/lite/pics/C2H.png deleted file mode 100644 index 49f7e07f320ebf40829556d168f45cc0f43daf6d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17324 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 a{n&+RG4;Gs8|xYPCnYW~Rv}{W@qYoAmxHtb diff --git a/docs/interfaces/lite/pics/H2C.png b/docs/interfaces/lite/pics/H2C.png deleted file mode 100644 index 027eafcde1f4f0779e6614acbd42e72a2628a78f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20012 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 X`?u`l20X!A;9z7V6vfL#jXwN;zxS{Y diff --git a/docs/interfaces/lite/pics/MA.png b/docs/interfaces/lite/pics/MA.png deleted file mode 100644 index ae38239628554d6c2e8fac48b5eed77bceeaf5ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31774 zcmdSBWmr{h`!|S)gouEslyoXxA`Q~gAt5aw(gK@}v~-trBMlUc0Wb zzN@~G_>XoIaYB^3`YaB{Y~wd9hpOg!Lsc?UI@9FtHy+?qoH*>FGfMgS$ z82Tit>kqsV)|16YdJ=GB@ZuPyh~Dv!b=1C%w&D7`-WDo_{x%s$xFmUf3q;C%834Mt?z|Pef-n_BZUviMatkQR}e;rR%^X>R%d-}KQG;*+PM)Cos1DZO;;X1@q04&*x<7Ht+!U(CldsngEvf!`O_CS zH$`~&?_ZE3de&jx+}zZx-rUsrxg6hL*yMiu>x79S)8kPFzSp@$0?Kc%oQ@zQG|7!`(yX2Y-4~yI5j|;}?+p{r~S*Z{Ts*APBcx{AXk0egsA%(qFvpUjOrJ z@ExPk>ivK2@EdrdxI#k9{f8 zPFg&#A^UGV9s1=o;RKLj zCx`o_KC=x2rw#15P--^Tyf#F?Bch2vib+?b)3!FwVXq0hKTQI=;&Q)Zsmi>L#-adf zGD9MuYrfW>wtqZf9$BtV@shuGEt6bTmK}_WOEN~LY*^=_2N)OG=P1?J;~SQn1uf@N zi7Wkk8(_b6;7z}$xEp#0@cvK0UFD=#vvqEh? zEC-&Yr!Z&0;XS&C9EJz)KNyDhz8?dbKdBsLF!zecZLW)b=J4lukwK8dr-Q^pXP{qvZra`j}Tc8ALTB;H1UWBAwhr2*eXG*Lq9!R0|u$67|>HsLCbaxQHP zflb`y^+{bMk<%#&Wkp$FhJ4z)LY*r+xs)`y6p`eW7=yt~Ii@wNUs-*I2F{lYL{|{y zf|=Spq7uH}wir4J80-kD)=KI_m*HJvDx|Mh{5V>7=o)#>Wo^7?G01Bu9C zcEkticDB>rb8`cO0q2s6aDK95eyEg{$aizrQ|r7p-$WnexC+&IMx(?!?7h2?Ar<>v zVL4n`bFIa8$yU@jGis;qW?E)v$WWA3@?g13qqY&9kDKx)RXp_aaCmiZVYw@QrJ;xS z!i2B$r)ZF7HD$X{x>XOyNVsy1owY7e{#D_YU>$>K6jf_8o_;gl8zb21=>GRr{1xbm|ayba9n(o@VVMC|a;`8rN{9Tw_y-+0Zz8kC06k1Ttkka%SC9 zrggMC=S6gWH17hNki#g9^19A1zrY^1ev&W4ss?9mn)X|4D<{JPFPty;%oZDDFm}1m zS5ugwn=07J3WJctxjg5qpT))_-5!p|V+NK(@0A}|Ubg&Hn1F7LQ=mSl4JLBFl=FOq zJD-8e^wE7sX7Q{exUO|bS!+x5YTKqRH1g)C@Wsgb8*C+&XvkKeG?BuYHMy8*NWaBG zOOQ<)8qpCKtWi4G_qu&8ULp4RgHLCaVpE4!Z(< z!pG~(;%cMNDqrT)ccL~roc)-z=9SaJ*c#-OS*~mj!b>9r$BO8UUg$miq~G6yIzqjK z&|djo^a55_-7$Bkt0xlS50)ae@VK_xYj}40QoP1$?8~w~lw@<&Ek&qxI-X3e)TyEe z4vt#W(^tRsc-SnBzyGty)0gi_%98V8pC~=ON`~W?qk)Mvv1YsnxwHho_tcX^@B&cV zbpzlTD!4wq3T2m1u^fLX$E2UeS>T!2v*e0OzZ-hfb8{I)bUiV1J&dj#6#r>y9>V&E zclN?!_ziQs^p2ic^`6MVj`Pighr##P15j*est89~N|hexhgy@0o@VJimb~hH-@fbQ zZakMypm22eVBgl^OD{Mww&O@7Bv9pvHQ=cd9SS8l&8N9hax>N@E36twYp>6ZorMHO z5)nqGMqldp=V|frX(h+EOTU>z;M1Jx-57sp&FQM3qO2I*&AYMbpY62YMs;=Qn76rc zVSVMZ0wHg?rmawzdaWi(F<4?W^lnp;W@RJ~)Z5m$vK8+@#S-%wO>kERp%-sc*IxQ= z#}Ev3&gjUD^r+~{8VzMrK(iC7ug^CMt&n1AQnL`hgOyL;9h81tIo2+BID|sM*-n;j z$b&V(lU>Z4=xbe3?LWCeVk*BYtv4=r5z+8Yoq7h!Ep&Tmj<>3IPPj#1Sh%lPx9l%< zw8UXAr)Dw_{ZeM%G8#JVC+Oy0F;z)Ij4`vDlz-@HiO~0kovHk5 zDNrDNrDr$kk^He8R~0kRSEiBQIiR7f6EW&3`SSX?0=py6Uj1J8fc!V-GEkF1;Al4LZuksw!}qIFrgK0JT-a>8l)f z8zhxX5qf~2e7HGQq<^^D*S}t_RQR>+<4o&-+^ee_(igYSrwaUL)E(|=LqV`19hmAF zT-(;NyEx=Mo}2POvMGGH?UY^>v1Vqdd48HQ^>{o-tE@Zxht_XSzUxz6K6M`G)5h== z(H@G4D@mI+-#iH$bcM()$=_2wuXAQ*-xJtXgR*&b{);Jubt?+H`E+gb^$7jcvFSv> z6mmU!khxdHR)u8$r*X5Yif?^4?ml@l*C<(iHyM4qLN^L2b8D;glA?9jM|tSk?9^Ut zyW9vbV5Kt579MGta+HhWZm!8=A#Y!&neW%EeQvX~^Q*Nk77`_ZVAE(sCX-Q~H_u#? zqz@L}XoZ?)49pih#J8t${aU+e_-gEINitAguy9Ga_W2#NO5pQ&YbzIMox zJE$Kgl8KNE(&0RB;k%x@PHZvLp{s0jzvc_R?&*s*NLYJ~*~`ZE<`#OMqPqwV=G;fT zy$}DzvM!lVv{NawV+76qg-`1-0pcb5?^d^%`Tqlm_n+9^AMYFnO#bI13`0N$WW4O0X~m!A`v-Hygw58 zCwHz<|0*t}i7(9vr6k~$I9FX%^sT>zR%F55UmWcyLbBf=XF74Sn~t-t4gZR@ zX~%@;Ai-#|7c#6dOV0EIP&e_Fxaf`~Uq_lqCh9-$A4V%DU_3cwY5f11p~R7ZiHU%{;o>&j zmIe}dgG9&D%kz=CK*K#;gE$f|Lc2_p$^1U_L?&HN#h*%2PM3S4e6-UCeWFC-Y45_- zzw{C%(qC5#dOhABTS;s|x>)ImpbJH%FXspNV5!}FtT63z%iQ^3p=e39P|pY928%>( zN&YcHvZOYQfmBBEnLG7=l617qj_X@{l%-mfegRn@6kqO)UdR~PXunvkNz<&c>#wpg zKii(zxn%t+k0o16*fP79m67nU>qRvY($$Y>UmU=^tfJpoe8iLxXW$Z%vWpXY04^^{ z5o>k4 z+g;C4Ve`1ZKv(pH^lc9h`?3eqKER{x^G$wBfUAY()t;U7ndCF1Xt+#VD)D-n@DyGo@2YwnszCX~KTb`%^^GZS~h_ zoH)*hkE##4tya!42GXVQPee+k<2jkX%<}VTFbCBx4IvRY4vc2Mr?CYzSEJu-sZZlz+2GLjEvXnPWf3eL;z3}`J z;VZE$BJ$>Bg~E2_20bpbp7$k;Ea=7%E#%4(h}Ucub}ZJMpjR_yspaLe8utHb+NfDP z8qtbmGahaokm1un6w}Z1DKQ>_!UiTwvEn;9o=Y19EJ{D|Sw9n(%{WyRn@%X2-i`VdJQzmIhFDLAxdC){xg{|`)a zSt{XcusmBrl9}q2iw0DqvMj6;k$;ABgIcM{H=I2F+;xA!i{FqUiHz?3Po?no_ph+C zeJZ7;*&qH+lSy*Exi&jg8F{lVy5lnjEt`VI(#VSrS*NOremT?}tF$(**lWhWy7=0Y zz_Zjwl^ABRaD$a`(%<-)OA^3X!jsq^9*gr%sw5L|)abXRKUthV!!^_8N3*XZ&q}(j zp~T>qXkN$4*aIiP(<_?S(1%+?$eIGx%ZV7`J<|ssbvijRMUMVbujube99h#!C?eyx zlpe9F9_U>tHJzA*AjbD6bq7A@&`lXhtI_M8up)ndb}UuMYBbrpM5pzm`f?t-E|^KT zxfRr}okwW}x-FIEvm@(6KhuCF@|)P;(vUy<{3Ejkyo)=)_u4bvEExieyMzMk}`PckqWaqr&&P7CGTeLa zqc3&MENVskUoiFmqKoFT$&Ky#r86BAd5*<#RZyf*{YP47H^n+6KfZK1k?LTz!I8^a z5<cu9i^qdD^GDOX+f+D>FMquo5N)?(uHq>Ad{OIc&0V`fB>U2iv$I_$Y(r3Vkg0#RzhpUGaWh7)J+Lg*UEXU* z1_+{6Rq$HlP3}~i4P&9zvas`|=Z$W8N73$phvm3ohWPJOc;(2z>(y1iGF2CbZ%3=2 z{qgu-MbgujZrClRMQU35fwKKhBYR&XxjxeDO_KR@BHKmGiuLTD@JvY6m2$4q<^yss zO*5oj@Y#&QR!OHMH@IY9@gfUF*01j813DcwiHY0yWD}&8A zqk#%511lg{{-IS2(DKj5M}_H(W_va9g&#LFy|k94*ryg><9t1x^Sa7U62<=Ufvj=# zC1!K3Ia7>t{kMC~(zbh{6f|1w5A!DkF4nk%u70y0qZJi+hGFYf3m0mB(~!^`FEiii zA7f8p@(T?eT3JHl%66)jG5oOmV))biz8^p339@+#TwafzXiWl-!3|ZD22JG`b@qD& zWVOwBY?{S0Gi-U&28YuYK;4c(+h9L6l(((6I|8K`-&CfO-XsN%ZULYvHc( z(jln$5cLU6DuRPg^ZzEzGy6QT?%h$kXQn$Rn<%?+T_1|v zbZR?f3A!6}{itu(N&9VtZp@S6pY2|f?*ciibaV&(0}?%(OFuMGdTRbqAzzOFJVy)# z2CW94XbWWwW=D7mB()-JhROD!=Psgr$&=2#FJkn)hy?LpsMi|~pk8EZ6wKQv<3EhX zWf7p>|2Mb2&Y*;U_f`ltL>?4L&V!yXH8|KG?!;S9&ypyR-nTg}Bqn)}>{jrv23zzm zJElv;MwD5S;sBME8KL^Zjj%#A%>QxqhdvL{SBNRFYwKg4n_>dQC zvO((8F6d_UqfYkTThh=qf)q*wJh@vE7|e$NspZ(2+ZQDggLh$sSI^Ud?DNt4p6i~g zUZ2pA|C=bhMP`)8g7>2SH`TZST5;$N=i9gc{un0PA-_oe2hRW?^pfhE-2ZHwk8rBX zS$Pj3S@7Ei8)xM^a>J)bUUH#gq3-{7yh2ETn}qwGg!_c>g~**l^(_&K;E z{IyS7W8|#X(jwb|gif#Jd}XaPe*Txx_$m$qX{+$M4pE@O^;*aky4owidvSRnBxj5L zJgnqRxd+>ukt2_`@3h;YGQ8sBk@81wdiscse(g!Xm5}D0QszCi1)5YUwLZJ~v^u49 z9M02{)@yC8j?{eOl_b7U<|k<|(JRgFXk9)-nqaKX**Tfq7GLSbd7HH^%Nn}e<&3-f zK`JluBI>=|5r;mZxkc~f>%xzNtDpa8!IB z;iWP?P1&DE6x0)K2fz5jOig?3U~{97A~;-Yw=al?lIm)cykcoNR=+cfsnB?YKGD0D z!mKyRWzy+ltH0D#&2TU?WYTWqm(%5HUrHLFn91fbM^bC`F88nA^bBOk5LN8A)6^)8 zmDwZ?{#2HkcDgWSYHkIdjf73Ejz%RU1TdraG>yNsqMIn9o8ir@xM(i_zFRc_BB5Qe z>>U)5>ZH0Y{?8l-oEJkxE3Hg7+)=Q|RS9%D(cfh4cJY&<}eXl z(_v3o+5J56>paTJ4VWR5$O|*q$Luz_j>;1ikTrQ5!W-+Ac$;@u=SOJ(J~0Ck`1G?) zf`6n4<$yqbQaqPUyJ1HBvgQ*Y9#Y{vThG&|Dg{i3d|4sOlA_H$FR*=e!dd?d;B+0+ zHTI#y(K+!xB68K39;dYtnY;PCanz0uD#^xls#NR6U@4!pI@R^sr+?Su5>Is`fPFhAm@VBP8@%|V{&qBqVIm2oA(QG`JAe0T6hm* zS_ths8LWWU)vRQ)*_ebnV8!*T(_!~F(x<*;;chPdHrKSLFBBv3SkF(%NfgeaytVsv#SYP3+yt=?_hm6G#^55F-xOS z;mV9ycrgu_S`^TRTjGHY)e_j4B;eNR`;4aZVy7;#cq?JjC(5IQOmZ7A0-SJz)!rY0 zx5raXTk7 z-&c)er~OqbanTt}BIr=@i^=dgz4~Xf+OtnqWBQR5%$jy<6eG2M^p&mgbzm-vTzsiM zIJ7xiii{=Tf=01_>ax6?c39|&s>N%jkwnr|%aPO1(J|X>OqiKj&=-f~o)>vqCQ~P7 ziP#;H&sRB&S+;zfEVmF@${#3HPn1$LQ{lqWz;1bA<wm;dlR^P;z(Vbbp@UJE+hB=ey176K5 ziO$ob?ETHPO;&S8VV_lx>B{@OvS$T5fGgrpu*Gx^mz@iY#pOV*?JrJjUk^zxrtNpE z(M@88tu&|X2qU^Bb_fQ-X{b{o*}p!zRG^xb`Et}WhMRfVge{RNxRpaA-Y z)p94(M4740K7#(y`iM7xd$FJvj-~C@!d%td^7)51_c#)e&PD0i=u1`lb>+JA@QUMc;{bvss}=UiFK!YG((qc@d|Yg8 zqrzQInGrTuM+ray}!{FMbVJXGvV30 z^f_H;dpcO6p*5ddB_twsdu!J4*mNA64LEFH)$)Vxoh2@-u z6P#XuTomh@GR9*wTTEYCWes$`xtQ4p!>US%6eo>#pnhh#H03%8bfXhsCWQ;~b2)Ku1MgCTc!MZLzZWZ}ir0)-6eMVi&j2;` zya7M3l2PzD_p#`_2ldc$ps-qONju>F&LBbK*R&M3BdBAHS*eaFoo>6-$|8_YA}fFp zm8cU$nLwDKPw_E*e@#)YXN^>#<~3GDK9urZqM3>ck#yN3DeUUuhV!=$(OLbUKA16g z@2S@qgE7AwdLqxJXYW^hRQ?>uSeqrjn!M5sYPzyrjy90@5d^UmjJN!Ga_SHiAvxz~ zzOHHkxLgF{noei>9JxytPIBy%U){L(TgfcJ%6qQk!%ZgY582>66p$ps7;3s1t>V8( zGuAzHacWm@ZfvNUY}5)%@Px@!e$BTjv>!*pvn; zwI)q#jb|uSakJ+h%IUc!g#-9$4j%i-=pkT*dFCj4G1lWmnGt8{t7cFH^FbX*;ToJ`pyjvirX=6BlZMyx{n&oO@a z#cmzqpX^~>E{e0qQ}zhup4z#toR=z!-rszhr=5R*T^g7Vbq~)X(>RCABhziS>rWN` zm=WVmPp=#)sZ`}D6hWu9yuX%wv^J1YC0FqC{K)F;yQ4>2G_B0*Mr$h+wptihHr{EF z!LDpNd9Z-0&IXN%{CxA?O@yerhjWA0_Ixd43HXQpwqMZNQ&Zg0c~6s23pY?-pl)pl zU^ml*KQ4YT_5A8ymG)FFdMNOTTNv!tI~1lqVL9tMfHLWcV*xA0c>A@XQhmIsvc_TsikgoGN~CdDGZ=@OptmBly?(X@}PJyesd`r4_rV)`%U2Wj5c`SAO;% z`Bg_1&_G)qe+j%9^zVE9f7&1zGtV{3bB*`nVI|vO$Y!3@dcDiq)#{xqO$-{c}}0uMP*UEL|PDLVt649?b!yJ=3v4 zu#m@whQ5IcMQE6zCZ;u|TuPsh%OP?f%ClHor}9sUzybrKt^-N%6?Sk&-q<*%Qf}(; zDH`Z`WNc*V8uRYmOBZ#`ytJn}KCfwf&$)zrgqvOutYI@$@4Aj6g=KpC$K8=K3V6=! zn4gKXS3xWn$@N{Ft=~_d-gjXZCXO62j)sp-X%+!%MT}DfS#F_4qe$P4S^fm3-<0Vq zA~TBKQr7=+A!0uS-{K3^=S#?R?`*RB zot;|#&A%|bsW5y(V!r;k!-6h_qQoXV0o$G4fbQ;l@sA$G@X3>kGsDXb5{XDLn?8Ab zD;k6lCm~AZY1WXE(7c7kYrgUCVbo{7B+Lzac>6sE?E9VR8vTo7w;Oa?q#=a|w$Mnmi=%1mq#&3q$F<<5t1|c{9_(H zm6X3FpsnceM!l2j@nq@G%uup=8fN^fAnd zVBnU%rg_34N@dAWputj5!SCTiP7`BtN~0QXSuAlOEajC5X;&>>`DU{-%~KeM@d9>= zs$^fhr@Y3)N<;=UZ_mM-(j}V3pt6Kjt<;1g^WJ3~fx9~#>>GVgxPhK_|7=4Tm33LY zb(17xSjDs7|9pPc+zWqq1$Zz^??)=}-G2}6J&IMAO@9pgua6WkVLC?=I@r&dC5X#E zAvUIWLhs`dV#5F4U?U|Z`}B<;MxwD~iT|F;<9lo-%|S#AK$#8*>=nBk`=+;GJXG@K z?-=!>D}R~URBBQZ|10I(IKTDG`{1g;7>B`CB`#%s#JDpCKccKcy!E)^q!M{G2J2y= z)H4C%O}j31ln_$?yMw07&EJibIkM26=xg&?5@ZBRNkHyf>WkDhZpro?i{F*fvwLxr3y z^i6fn?kk!t$sGN+x7t$@E2h{)Cd_ACP5yD(qaec*u0RNKLcu+}H zf7TZ;YZ`Kg9EF%wCbz4OzJ}$)6g&^lZJwnSUaEgFo-8lmzSu0XZDhbU?T&3u z$4E_8SyV`D6^dZgj1CKZOGiOSFx>qF`|-WMw*wbL%sy45Bj=yYv#;!{D4}htx@8+h zG8rcprDQNJ%O~&J2RWKGmBl7w@(K3a98?jtOC~Tf4;hf^PZmZs1SB7p8nj#pVE3)n z7%X>nb#<3o1)jIbboJN}3$#;(uPgE9(jZc1qZVZBE_crkmL*yO3F0MxeJJ@3MDo6- ztRoQ3yp{+4!wT6gG$x)@`eyJzK5G9yuJwIa>2RXmUiqEv+jJ%kKzmQ`>F_e=v{?q-BCPEou|q^8aB z&p!r4EWM^F&AG-b0SEvihrsa@c+7YCr+lu zRq6#G$YAz+iQ0=}uE;Im|ApxW@hII!id7qOT@)RuRHSiEgeq7i5j7I*6_x7Sqoip#4OuASqYZ=CW|N;c@4La0w4ETW zYdoB%W{`vV2^I(K&<-Fh`ZD)cmk7?^v6l&d*qjld$&`xIdA|Thj4%40OI9fGT7J*z zn4vM>qd|llRU=>9#kedXPqnDIjT5pet6ax6C>j3heVn?E1uz(;+NCRi8OlWL!USW` z1AZ+HypZy*Jj!Fdr?dBM2p69ZUq>}y#eF@3S;wL}orxR-L68V#{`12N_Ssotl#bSd!HC=ITVl zEblRoxHX#lQM@)s0w3#EEiTE7FhP@DWbVWbCK;1zyA7cMGc{cmotqb^%FB-FeW4Y{0let; zPK|VebU?mG%@S)dqZ4>MH7bc@Y>XUlxP8Ngi7e$T}$Gzo@ zP#?nlg@72C_>d>B%6)Tru+7~{mviN`Oirk;`Qz<_k;e=^1o6yJ_vVpbo?az00}~$D znx8ktzS(0OwEOZskMN4XGO==~(5XbVe0Q(+QbfaM3>wMItmeIGl_E#HsSK=}pIy&pZmzWWekyw* zrdA?0oJ;4w=t=ai(yBOms#FH$c4(TQ)#zSvsz8srY4u z429yswTde_=ryEneV8Xdw*^ngY`v*HoMtMFIsW^yBh2zCAVd8)Gv5wEn6wJ%k`@Dv z5WC5rd9~}=s2$i0LBnj8i(>2qDKJ4Hm`)+XG3rVLgjKg1+-y0m*U33G7-;DUpud?H zt~k@Wt(H2%Wm=hYt~96fQ=~2WpkJjkE=IlNV2plzl|tRzrr_dyBd;m&i>&|>fnWPV z61?+6tDYr9q%=BZFuZR0U z(qSm>HWkNDh}GJf*>^_Y2elGkfo3=C#h7f#@PhWk|^1{zgG-~@J0x|~*&FwUA8k*K-VeWH2d$=SVum^MK zBcJgBVPG*#LE2)&qeIm*S(-&93s82G)=(j`2K6_q-)y3kZkhAF?s{fQ;KN^J{#LJe5QQ31 z|E?n9#AGRy`i6WI`3Jee*ytP7p7hrVAeDgstRh>h4&o;kBRxa8uBOWsKx2p(usVUFX;MTN?zvHCm}+n*s=)x7gND5Qh9?B~mU(iv8Xif8jQlf|~7YHxm-GnPE& zLi>ZuTm{{E!WMSemBZXyE*?th6YsR}S`FC`Ro7qy&qqUH;rZ%%g8^536RydgB?TwC zC8}}V^3@98%^D8XE73*>`Bv$K8CDgcIOI@*4{E0)xu5^q4#m3f>^?g8YKITz%VUl9sddjG|ver~iD?F4aWb+R>pfsB5uS3eu{D z4ri9OAV)uSrIhz_s*@iK_|T~~mqOYQW))~QkuCDkxLDfWxR3Y<88+%sge8Gl3^LZS zy_rOJ?kt9wIPuh&6Xyvh@P0K6Fd@eRBct(kljGqqihc2AC%J}WRdZZuWl!JM@aVIR zl$GDo)>HQ=wilXsRR@s;eB0ZK*qezkpL@EzJFkq4f?jOjBZIi^|et?#B|iCt7Av+pZg*U9TnEdyCt~6JO;rZUq=* zTR&C0iD6%bT*YdJ!a8@6>02puTrJY%ktHHIV-da3hrTd#&G9{_vgJ>N}#-|4C1)^{Tt=FmvgZsQGgby#xlN@8|mB(Jv{fik1x$t{XBm4MQPy~NQduv9K^cqGN zk+6E%G$iTYM4^&kw2A_E_bfB~P~SKC8YfF!t1h(|0kXnH_-ggxf4C3$$(ay{ZzdMI z(B6I~OATMyL3tO$YNrQ`tnjD(2N+*UQpAvTO9$$IS~49g{4H~PC<-{`m&sOGP!bN_ zmY*Lj2G~&@$6IqZ8WBjzr0}=g`zaaN%SU&KzT5o=^T6+IoB?t_cm3HGko&Qp?%x5k z&B5@l(=3vw_E@|lmZ3%40>XDcp!+Yo|MXL=9Y)jPT##X1iTV2&1hCOlCI2R%@VrDi z7Dmt9!8a%?g0#1X2ExMC48kLzEg*j6Cw_3RM)PjH-CK$6+cFosy{t~m)tNfy{+9-0 z*O=Sj^rIIf++aHr3a=-Dk_7u?@3x}dUZ1`f|CiKHAe)NB7MED$7K{Ps@`NmDgl0s~ zXO6+L2}mIWJ-#{6hquhtMI95C8~w}lBYwWhy6Yb!NB|2vdW2+JG)Uu}%TMj;T-c}voXb>SN9bc|0Iy9%G#&16sUk46qu-aV4o<6&Z7vZD^-pCNyJX=RksY*&RXve zH;3c1mA&6hb_vTY9g>j2CERW;#BD$n|zrJ138v)Sacc?uwR>Rb6bH` z5udAF7Z{9hSb*V;eGRN({EKg&?T$Cs=8Z;jO<~?(U0jX*aSVuM;&D~Zd)X!c)`Vl< zgipscy)|0UI2sb|ZmDH6W&H`5!SsI1Aa^bz2{jFJEHV=be1VIVO9ia=gaR@yX-eZq z6{jG-H&qOlJP=LqD*oKpFzPkswr_iH+-xbi&@gsuHL{>N(oedXS}tDG*3LhutT}pt z`RlIsK)#M(%MoCM$3^5nTLMX=T<#-PmcFzy{)1<{nbx^Nh5QxF6#WlnW?LH&5EFCC z+2@^e$5OB31Q4PNK%Ouqb>?mzM;TQhJjM|U)2T=FE9<~ z=W}j~1!u|raP4!tik-P^eio8LK+n9J=79GDcmYVbe}z+GSG_ zaet7?ttgI>o&v%NjMSrNtKDz#$NSY-`;2|UX*7Z{4?EMk1)mLX{4|M3&PFp37IB&wERW`}`Xoun(|7znOTG!l?3x4Nqk&;RQ=$e~nS`b`G2kzxzT3}l1~k7b$=IqbS{ z!C;|tzT^4{4$@WI`WqncbamX=jXlF0ejNFY;db7B;5g-A?*eeVPxn(f?=fAWb^}7$V~~sR$yF;rbc3w*3vY@AC7Sn| zBZ?P&>RK%9ptmwimyTbbZ}!I}i`2BsN~G5aa^!!`)j%HpQ&E~-Lb4Jh;eF^yWtMU< zDWO7dVSS!;rceZt1c&`Lw?ZQ|;KZ(^Z>f?A!m{uMh_Mopk5k+pN@DH;{4``SlI8lL z2lP5pceO`4S^x{jf7i^qY^E&6$-2yru z4&(*#;!pEn+Q{G#(uz&wcuKv>5c!syhg?Z171LTabDd%O`wN;vg=;sLOcQk!l|~&N zdV&I(5wIAZCG!Y2t;pkrhzQ1{m9F?`owV{Zc^f@&&x=voO1 zDQ`905YhhR{`i6zj3;njFwm{Hm>ELP>$G>sHln`pnmmfx*7t?uVV@cKABxUd2~iYC zOO_D2F)V95nx!u;F@TB3rQdGqAI#b(gLyuD1H$q?;^`?bthc0<_oN5bKMVI}xunrQ zOVLh9K5blAEpYIN`#SIQG2@d@ASBBot5OylFx3RWR4e6R-g`UPGad9*(gsnCG#Wo0 z*DB;syR<550P4bv;S<-R)P1iKzW39Rg~oAAEziK#S+GEU#+bDW@J#qFjw^hnGe|x_ zIfo(kmLJXSVy8;W31k>LV508HZWel4CD$lSg*jUwx>*%5g4l&h&-BIj!<0>ENF|GA zu?idUp@8!#pJzvH&4u1v2I^EqFEC-B4BNH8%qW-p4r_mq5|xOe#wb6(7&0Rlv!NRZ z!h7gNV#8lstefJ@jjQ~}%>_ki1nvFxAt4!36mGCVBcGKy_(+#o6b+rKPEf&C7 zEj_;nDy@nIHjf2h{V{tro6eMt8BR;@Z>2JGp!W{?2v&{?FQb93MK(|8q}H$;%P@uFs@c>_>k>k}8y2Q(3$xCeP@s10o9p;eN;;z=9s~o- z9>x$n!>B?lHkql_*z{I1G@>-Ur8J<7CPkqrQZMhn1g~15CUp_^!>$NGf^-;YxXH&% zf~;@E40ve*EV|?ypGkc%xI6^D0x#`lWoj6J*g*KLLI)uiNj^Vl zqTp=~6N4HNa0?p5%%``(YaA5Ds~ns;dDc6^;Q4L4(ChB47KIW3^=_^wM8MQB@24($ zH?e;$-J$319-z}Pc+-wmHO3 zT>Qko=L#W`R@6JE znwC0&^zLeG5ExA?TVi5h{|R}3i&tdzxQhVHV%6vG$<5x)1#lNU&A=w$pdsW*o?WMV z3u&MkG9--X#~r(|2Ww7Y%Xh$>!A8U_2mlLHf-W!l3d^MzBa+s)!yhbzFnUG%PhtjjP9V%9d84#k^%FCEjyLucB8vfz@Ux=higxtHe`b_qgG7s z`5Q{1$IS48#1aVQnnehO?!G>^(;>4+7Uommp7`B45P*9$HYfJ-pS%0Uj{@4MUy|%9 z{*@AM8S_14JufgI&^PiA|FsL*w+N&C74G#4|EE3s59)b=Hdxs02k$H)%{LsN1Zh&o z4~F83g$TXx+x9b{0LKBYi1i^A_68epUQa{#y&e-R7WMGSsI-H(VUT)^y*mQc^gC#e zqo8Hcf(I^*CTO&@-xrQ6UPK;vpA7G6IthqS9LSN$gMic+XckFc6mN`SH>by-FgM{Mrot!l91DapTSpv1bZlc_aOZ3UxlfU_s8C?7C6^1xAuRHWYcSbQ`Q4-tO2%fWa}uCt|RU| z4-8wwJX7%Y73xM$w1X7j0#Fqu=&d#A4P5HPE%(GSfLJWVL9N7y0)$tSwbBaD1`@9q z6I<+Gn~hR~N8F0Dw_I=EP(A9Aj>Z4c*?9(H8UAlSQXxe)C3}mKEx9Y%o2-n?LWmH` zrpVrVWM@;7k(H5|y^6|Sky-Zhy>9AP&-45LUp&34T<-fC=XIXnaU7qsA&=eAe`h7C zIvh0ZWeSLG5Be0!Aqjp~;Veig%-S7|CNB ztDJ*ErlSo5FKyIzbLdtMX65!@v|e_~FLnlH^rE)0BP5&#D^ARS!zpTg{I_JdxN5U8 zjwv_bnqytJcQa|@b3?g!}ooFLgkxFFzM+Jm@`cV zzcIpw)uh>#R{AMz$zhF$kPv%2q{N)mpUV5e=GqID01V-7{k3b>0Cj2%WT+1p{L|$- zl=ccT>48PHokU$bBvNU0_ve>w$C5onZkzzA+QKJmL$a)GM|h|f`PF+)ME#A)N<@(z zm(2*_o|yjn@omw4l&r-`H6O9uk%#vpDFf1ZB%@~1L&i^8XGBYZc%BabINktsAsb%v z4~l=BDchWiQ+cD=dUE5{?)J~K!rjw&6NLgFvozP++0-SX1M7_N{dzpW`g(U^CcH>x zR$FA&#apLfHu73|C_Q>XZ!$`{^&LKhTlEBbc9-;<+ z^=SEWv0`uQ?h;y|KIu$B$D{$>$8uFV5wQ*6c@xW=PXN1|eA~s%IwNeqR`2`+f$v5R zt4hXOQ(K`)`GL+XKP$s8?Ay<&1Vd=?@uYIvg>U`PVy4F$@sXdFr>Pn!`?|r9DiUA~i$jp$G!`Z!umLg{W>pXe69#sgTus$0*;xAt zpAgH0HfT^z&KFdZ3g2q`E|gBud$C9*%3x&_m?s9A*Ss5NoxH88Hkp``u4eU@%-h*Y zu#b$ev8cT1r@H^?jobo{V70Dup$K%77;*z#4CbZybuI>Ny%(7ETt~F7r0?eI9_ zU{VO089ljlBH?2!Z|meOLvfwxC;Hr84U^Z^*&_>ri4?9VE%00)NLu*dk66g_<(4g; z%zS$mUwg^^vunSccZueJcEj10@;yl%jrhhKrSYK zLlCMl#OM=M^6lU`(A|JoLHGf$*zwCAheO-|=l*b|6r$VcQVMi_{L|MmFXw4n{z!!w z_0@H`s=$eRp8?%fFK<$?rFyFPGm07%IAKW>_;G zdmvmX58~sf3V@Pj*nED4e7IkEA>YsMpVT9{^cL|>e7}o-<%e6YR!Pg`Nk2qwp^u(A z<^2Z8u*%CCy~(ILU#NcvM|*?(4Oz26hgpH^G|X7JjA*|bj0>??w-Keb!TsKgNNXtX zUD53maUBW5al(sl-+g|d^^@3k#DCoGP^}+-uZTK4HW1V8I7e%N0VH(Obt(ok|kxgmv?z^ z_nzWdu)Sy~(V(r@-PSzzx&TqhMl3lq_9#U!=v!+oLXGv2VSsYM^XOD(MY}l4tj}!B zr{NX)N|1Mjxt}QFFgSURLJd&<2)l*lX4KA#QPG;H;fVr$S5%MFE1e;|{VjDzP(2&I zx%P7odoRkD_rBPt+G*Ay!9(hJUz`}&-B-bcBLejA}n>WLPFD`c_ zVJ2Q;*~L$ZC}Gb#?az79SYg+nS?xTZiIJIk8EL}4-oTks}eNgPnXQX zrESG_2NAgpx98J&-r)q8G~Q?V{?4+DpQ4CejavO}?y+EvK^oSG;X4TaMtFKYcHH%c z5$NHFFaQfBQLE?Wzk_cSjR6+jvVg82*tJkax8#8GcKY(S5XaTrtTIX zr3g+z%de|bg_|`Mk;tO!!GCTv@=-|pMKTMA7M(^MM9%O~jUc`c4WUJ(t%qame>fIE znBdb1smrC_oJkEz1E}K=>9dvR(A3Jn{_){JX<9~q$G=&}xEFFHVqYjvhx~|em|~g3 zPtB;WIE8t5{qUv5H|~tp`*s6%p;#&up~idLllZ@+=Yh)d^`W7T zEI;+aANirR-CS=7dqHJ)!|VW5jnaVdf-pC?^_LStgQhY!P{4KSEMGX7>oy@Y4vOTn z82&YR`kX*#&`GDz^xMFZ;knm|vaH^?W95R_p z0s_C2b+|z+oR|oy1}c_n=bdI~HA^iM;vdxE6yK@!2=BAdsMh6t`vddt+g#08;^)Cj zzd6a}$_k=38%Om#Ek=-=Mu3d~1wgjlYHq_uJfMUG`8{@=YlS4v7$Bc2-A-!x+N^pm zo9X_J-;Qk}offNin~@M;Y9MGbdWpbrXvMTZENTQsGVZ$_@zFNQ>Dw@uO%}dC9i||< ztJ>@1IOfYd0Ro_K;Gwh_N9iyjke1w1VC7Y9Pt4^MkXo2$Z!}`p_(Heth6MWQyGs(V zv{n9;reCN^O5C-LjhbHjrkVL9-9{*M1%9>6^p5T@#EQ*= zIv=ew&7u+Z#ZN@U6Of&?oSI4x_a{HwOpE0lloZ0zghv>9ci;neP42Wom484vnV(^d8c(<2GI) z76d_Uy4`$#?F{)o06mPrSlRKQ3;V(n2z5e{qHb3>6m_4sm|QDN_B2eV$x5a)t`yRTtZGGOZQ)X?2D`4J%- z-O|-G*Zn=4o_7ASUt)Sl<2JoDQhMKfi~0G+dmuMXwnnu=W0DITZXo^M%0g=EHmmLY z6=x`U-^B8nvq9^%IvwmadsA4t7_%9x-H#=Vm%C-S1dkQ~+t<>$Yp}?0MBc*Nv_Rdm zya_@jKW=6Ee4e*A76|kf>T9|?+0Y`8!wH%I2eaH_6&iP+kJ|Gc1AbQ1u;PtiL`iWt_tQMBNonv)lNsPdvS{gQmtBJ~0V&yJ9&$dQq2=B_kipY@#GX;b zF_E2)Q6@M6O~(iCm@vX5YDd>zB}oVCDZiF#tEm$9#Tjq* z_j-?9YOoz9oNV`4ulo`#6Qy<6ICBwRYj#8lms0l5Y(;7>a#dom%>Li7IBXI|*9 zx`P9b3DSmZ$+?8kNqI8`E4KY#CELTN@lTcW&*I#L(6%jhX+{1-FmQOw6^#Dg@J-Gm zXyeK6%MptM1Z-D7b@$&Gz~nZFmRMJHjvV=Y7&_44gXrMiJpL^57KKy%ZwiY4EaL*0 zPF+mHbbVU`H?vFpoy;%GX!qWt38REf!g;L`9>2ovm(Si>% zfJH11nGe$it=GZLVa%B%{IIZgg+ze-LI##<1flkDlQ6&^JeLSpfkh^gBLvpc58q3_ zaDsa>0+zI9$X(`EU~ZKI@d8Jbwv8{+O^>1-efY0o|Dvc6B(Ze!QjwgpeC^bYrl0{q z;+LjUu-&YT`Eec3@vr&<5%YhFp^6?@q!+Y|7S`C2_BC_E|5w?G_qo6G4}Jt92G)85 zS-+q|`NS)SWdp;c9|63w+Lehp2Q6=P%~2>lMOThCH&MGTtbo~d(gd6pQvsT<;&ZL4 zmNRh74HXj$ZS{-2ixkx$Lg2gc6mMBmW4sFikr9ckNQj%ISVeUon3RwK2~0^yD2cZ3 zaNUi!ehOGWC6_{#%0PiJ>`mz1f6kHx*22iW<`>V-vmqk+%B{H^Urk!7 zQSEwu>gBDR$hgI+^e&l9o{jd+8G#<|(uH$^25D#Q5SrEH zD?G{rX;~`o>*e!oT$W(nMq7uUHqOqpR64F!axDG=YJ#Lrg>EJ=rVy;gBZcL?FsMUZ zxMX_raf-#Oo{4zt6yvNS>s}=ZDUGw9cCesEOYG{$+Xi$(&4tDuHz7$b;GA&7M^SvI z&{?i%rY}3doa7In`H!uT#T%qf_xnD(Jk3n1qgP z_>FPs&NHNn2mD(YdAzZ3CeO7coYm%5wM+MFQx$#@S+eEB5P}2juU91V#V~|I4F=wQ z*swTJdZT9v5P%5SJE|{#-g^Bs`9&0rfn4Sh+uAF0_~X4GKT-0ugtoEpQ_vH$01Q2r z*q_UXi>Y`TxTm+MJpN30(5vp$`LI?ip!5|4qjdT-ms3mX4eAJ_dWDQ+mV>J> zd_m7^)+w^Oa9KIil1i}PlVdl~T*_vr;>P@Z7dC0j`>q+KOFTeli7c0~QUs_{+E|`F zy-pK|`r!ojLWYFV zdS+3Iti_ZW$W&AMgDL*3!xMssZ8P6D(k5w4A0x=FEyFR%-LL?lMViT0cA%I5XUfbv zs9MxZcWt0$mO{&;yaiCH>IP70JUh@xqR*NJdQSI?rNWBqU~%y3qCHTg9$b(l{OGw? zP@5_2&>%%b-2B%hiz|UT6}LRzR3Z9~LmOwp1I(oUu@A1+|D{bda{t@==-thNiCKhn z$|6tP{cAC7ki4_CHk)$%^l8i?259BT#fBfmC%=!GhzDb*O<+9kpO6z-o!##vyGDS5 z&jbB01A2mneK{6Ba$-F9E6flJOyf$^>Y{Ct*I$bL8KCGjViVaJqk7%b_V+iS*H{!T z7BuZY;|& zEZo&(b=+7vB57K8upLI$sWtHV&hth}^md@Vx>@Vo6Tb@}G_?P%Ta{$_KX$7m)UwqJ zI3Y0#hsIpTqzn%?QZ$GWuukF7EEc2uFHFx?M4vVUTWKIxMQ*Sd>OFP%nDA(nb$xyy z3Ph7Fh5GMzW(xVXd~=yK%P$V`K)vYEd6Y-+x5lgGqajd8t|TaV342NRZtGWz%|(fYPDOuit* zV6F7Q^--KWI)wRw$-H`Rdz50@D?Ti2;(^W7#C&$xY|LnN;%rRyezov3SzX=4m$ysv zhpH^%d`aGzv{Obkfr?M3d}rs0p*NkO=uSHb#pFy(OvD}n<;u|HW1@cFiXF7f;AZ7Qe_d?a-?F(|pDk)*L~(076K zq;W(}Q1|`s;YnbLiMUa>^|=rjQwr71 z;-**!khdy8U1s7n_t4Og{B336o+5oq4vj(-_hs`Yytu=N4pf`0vGOGx(8P%Xw`apK zbBO;q6U}&`3A@N6u*{GPX3vSKso^c-mIx8254Y5H7?_FA(ng(hsTQz_5&;jfrZ4a#i}H zg3(b{32aq146j(}28D0v*Peh2!@OF_K$Ya4W%(=<&}prFziH=EV%acH3+1(ff;j%` zi@bhb);ZOSMH#m`mUbzG?Q;QM&tnp8rjC2^L`nse8|vJqa}(I>PDjQl)4Grb-01 zfR-VF=HZXdYqJ9dNm>0jOU_a9LANjlU^RohbeG;Ql#^;!*yqVS`t?Jf;1=U0m7owUmUiyW+B zfk%4Is`3uydeayb`)HKh7yDc*=g9N72G|f6%S3w%d*Z2Sf-GW8Y~BcughO|C3YM)p z+ivIe8!Aenvmtv3;E0lvgiou)l9634HyGN&!r!hvx*iAd+3o$1J^`7=fV0e(P1*=} zYoC+Y18wHH&aWkV!X5{RfNbiXy6g-Fh#;mO{AYNETwX>cS4QIKc#dnJ|vNFVvm6wjX$WY$pkG$%< z{o%*A_mhc_msk%kfmw51xp`|x`sHcw!?jMDDS4m2_ObCxR4UWm+Wnv3yd&acb6^GL z#=%M&Fp8AX^rayO-RoSvY3K=?;B%wxk*WrmizH zQ-q?4$5Oqw%)`rQk`n676TvYqDlHS@2*ri$E<; zm-J$ZNwQ+kqj*EDw?dgxe~_P^jk;ulmo zp-;(K1*j2bxgmQ6DSM)Fr+InJBrh18!8Y8d?X90vsyhgAjIq6z8RNKrWMN~4%DPSS zHrEhoYm;x|ufD?if@Snq!4NK-A?iqM?8Hh25Bj>%_Z_*TwOF0K4CE|BzbD#*bhDY! zO)*S+H2gUFcKi++7^06{m-BEBr9xjzJUM3h0}}WWFV7<%%>}ktwJy9Lbj^L~+aITm zWKaY)m`DmoOiKE+l4MrL*-+MrKe#`g$GtG{%yZZA=bBKJ1 zMjmrHYks`#`8{Sgw~e6bmDSaBC~hLtCxbVNyvfJb*|KhsOsY(3Uq$lDZs4XS_hYZ( zzrXy5yB85EOG-eQ`(K+$s1%H%nAfcTLh>aAU{3a;XT0(6bBKXAB~&WzfBRtf6@tOC zhnWk5Rqw7yNgcRzZpFhRA*sf=cNMvE#!k>RQ1F_mV);XvTMCpYY4;>TTz8>28iAB4 zl3e#@_1G7YR67l}SX#8{)Vrd)yb4S@Ntdn7>9MHYRiw-h5@LGzU7O7$5FD=5o#guU z&39$z*LV=&=c_zQo1yqvb+TVUTL0iu8t?pCUKutoXpmN$LU!$HMi35DwhV5lTTICxzjf;0m|Pmz z(}{Gc0C?@mbRd{nqRIKYBeN?YRcL_}e-a|U5al7>7o|?H`wm`K;env& z)ehm0?H>Sips`rFDle+b6V$OX_bjl32Ws+aqp*t)*{%KM2{7DFJUwd}Own`qT$Hw` zgUcJOc&Nu{3)#=HAbTYsdaD&gm$2d1to3^57Rr3IvaD6F^(yRYF#(TyqgBa08~R)F z8e34On&`i6wfe zx23yl!f)M98J>gDr-Ssj1i{9U4)K=_n2fd~)C1m`_1m56^W`Fu7s=G3xS;UfvTTx6 z5P~E!2IeP~htPaU8O#kit}MCJ?!H=yg-G{~%{?i-sM1hBfj+1#NywioMp@yxktCbRNNWf%;0%zptJ= zC*%^8!X7$mV6;Q31I+vf(_?eKyMx?X1;AGr>J#MR`q-Oyd*GgCQOiS$h!u(X@!jxa zr!kwE6eBMgAS6qd3);#K+Pv#~c@TaMRoq>&)~`LOmAFfDTGz%!_@zF)v9_PrLpdEj z`k(KaEn}6@n~COuDoE%LG5<1MFNl2K{;FLTnE5&8C}D;71WN6n8AS$`U51K{VVv_? z=9b3Nxt=R!YHpO@i?%Z#C@Ta@8Kv+UV+c5=7b)`0xf^A8csDrf&~v|=&v3OX?80`s z0aR6-XqGv2R68bGanGg<*lx(*odPS;g^hHU@vQ}_754D2{z%T*?%b!G zGa(?mpf%Aw994*S{z>KRQ#0e@SFc7m((^GoHShKr7@PD*I<%bZrxwNPj&L*6LOQc{ zbN#I9M0N@Bmc$-@Ni`73By1qKe1)cZu?mQPD>!cD#vN=JG0*1Eq;>qI9T1$HAt6JEsWl*@nxM{=PopAEe(Ul20X1{x|rfS zf}{JMI<5xj_TzDw=51T+bY)HQRC-yK6JN_9lQ7`@WJxGBKy^GJwt5yTL|$vQK5E*Q z=&03>Y@>s(;&{k3Hmrup&xtzic!e(igx9DA#CG3$I$;vrE7u6SR4Sl%6jFuq5=N+c zTW@@JYJcqbvYH{2OW1sjvEQo}zyD@k|NVB+ps6nJ?S5NXRU&Z2T_BS?#yY}*Dq)^8 zm@KIC#pS*BXxpN+)owTc;k<_`J;@V_$IEMzd9Toz{9H%fwiS=%g|@qczLp&onfnkN||%xG|BVYs-DW9jg5@n;;v$N8@1$h}=+%fm>z?&!4@l$>!|;b*?RkZtugHDmuXs1jT#=>$)6@Y`gUJ zWy>vn8-U?#TXg9(ZM#y_Q?qquIouBg z6J4(3{ftV0&lbCWacORD4oOL=21LGkhP#-VR>r6K`Dh17nlc-b_^lH0DmG2{hfqF1;4qq`0y-ylGqVtn9f5dTF&EZFZ>D!Ux z!x}Fd2V;Z{Ewbg{L||ka(vfD9q5=6xRRsX~yqcHP=D$rlf`<6*spE;Rdye~BovD6` zdBOU*QeH*#xBWAyVc*9hCN7uP_crInG3hXn_*t3(A>8T zxGpneLor=G4b5FGtKE%4X8R7+wgAY_Y4=JebuacmGb)ZTDl$*C?zj=ZE6Td4+2uW6 zj^oq!i;}(9p%ykjF|~{DDjEml+GW^3;Kz9Q)N)Iop^ymwaH4}wF1SO2ASaK3^ql<+^0M}q9GGVEcMe&2+{ex} z?BKf@BZ0o+&_yCThXm+2{0kyrJZ5OMrMqI;uaDQi!r+?5+$7aNBIx9T5OtLujH^Sx_>_+ z0lvJO!PfWIdjL~N1SPM zVAk*XB?%RkOD<@I8{`6Oq6&|zcXoEd^O#AHbn=-S|J9k0ODQ&6HS7^pKP1EVeH2w( z?9={@*OlFBq|~^1SQYWJ4^j)}U{qHi-KPC)DRUuKaXz-YJe9E2d+}53p~p;V6=^X^ zDCm)mN}=Z!0^8q8gTkF%HK>^3^!UTDurPY~XBb#weYmZ{`y>%14zd+woNh?fkIPbq z3a?%6%E?ha5|Tq?Xz| diff --git a/docs/interfaces/lite/pics/absence1.png b/docs/interfaces/lite/pics/absence1.png deleted file mode 100755 index 70b4c9e8d22753b506682086f11e442a7441cbb5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97697 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

3lE(0~5)&o^Fq;k9fm>rMfA^yRsE{JL7~ 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

aD}wU94-=NdKwuYnfXBd=y@ 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

MFm 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 diff --git a/docs/interfaces/lite/pics/absence2.png b/docs/interfaces/lite/pics/absence2.png deleted file mode 100755 index 6ce5bcde31dece5528a36f18fcbea1c98461ca0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31717 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 Wa-vp4fIrE_QdW2>U-Zb>@BaWy%|5CC diff --git a/docs/interfaces/lite/pics/changeProcess.png b/docs/interfaces/lite/pics/changeProcess.png deleted file mode 100755 index 1771c239b92f73d761ac77c06a5a11a435321f71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8919 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 diff --git a/docs/interfaces/lite/pics/commitValidation.png b/docs/interfaces/lite/pics/commitValidation.png deleted file mode 100755 index 89985bcc12eab6f731d8d2332aa0b8822069d5f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64713 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

  • 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 Z@m8}L+OwX38hOqB^8hcDG6x=q+2-TTL<{v zd*8k9{qw%}eMi4@;IQ{vYp*@$m}88&!;};xG0~r(!@SC*gSVBasFJj(D20-fy@k~qb2vDLSW_b-M(Jk^J;ugHMm>W}Ptl#+R6;`|RgBs? z+6UV^C_0V0C^A#@^cElEEOz+gdpG@PN6lv03LKC*y7U;!ul2ru_^LeBNrRTB;Uoaw zO~%^sB?1C9%7=_}mGtxnX6ta%JiSQbv_k(dD0J(abKyD#;LRck;7L)<7T_z#D7UdG zT=7x{J0TkQcz-a=WZ|YE(l~Xb>QH)~hZ48@k9CNDn{8K_jP-Al zMsDQJW91e4+!dep=m~}s3Qj+(J8J_g18WM~V^*z~e_wJX7!#NaIf_YS*i-mt2le4S6gJ1D zL~Rh#au#|R&<=+$gi2FdMLS;d_SnFVXRf|U+HK+YhM$k&=@;FtB184bqMi9xVJlHq z3OLB!3zu4n!GxQV8V3&k?nMc=8WH?IeoF_pN^HE?gM}yr2YY?;9zni)Cq(fbe4@r6 znGS$M^@qI@SZ40up^BxzCD^|Upys_ls{f%l@%`}wQ1Sf_qgWlxQ0@ny)cP9Xel$47 z5T#aJ~qsGPQUI7*<&(EvV1w~0L zaY%%;^|9)y3`k2pmXVb=An#Qv9k$8gD_-q+YAS&jcxHa4OmbSK` zfy?@L9W(#&Pf_Rf47W7yic#p*o}c|ZuX!q)CDs>%79OhU;Y_xV3K=|!OyzF#9`utw zrE_9&ex;S-9vz}!3HkJ5tp(8D$jwRZwVY<=s?@#FmXVhJ%whBEX9&5k6!EJ!pR~yb zsWf`tG_0&@JC>$k3!Djsd#*%rs&s`DcD0)I;%Sz`b;^)_N~ic>4?#yp)RQu5_lK9^ zw1Y;H3(l9k^SSt^?zyMQe{*@X*&cv^x8|1NOYdksUikS~rS|J;lCIiFw)h08+pKZE zBiB{M@-bL=Mqd)w{l#zLbNqvk481?^wqDrfoqkl0r4m@C`~CJkuKzd5q#qwNy;-m;B|hyVPL{=ax^ShGLj=%^3`Rlc)2Tr zsm1cS`PsVQO)9-Nt1)*K8LAYiLt1*>yq`vnM3joCtmo^>8GOjBnjgui|FtGnqRsb;X69QE3L%rOD6Urd!NEa3-g>*Ip?X3!N92SZ z1Ds!mAFIbqV$_v^`x27szarIwV*6I;kLLA&&;n!gJ_PKNS&fUVn@dYJ88G(IAZ&rZ zY;z0O|LQjjvV32TwHmCJSe_QU?##qtV`rCEv1nBYjh=Qd5J15AaN!vYAE_gYHA=Mq zeeLmzF!DtLi`yt4u@|_WV#Z&zDn;TN*E79x5hm&1PrM!GFVOg+llLQN-jY8Q z#Z6>T7TNGIM05FVTQ5DYmtWIj)o2p^_{H~x67h(K*8fVURUT&czV$d6ZJDXJ&+0^@ z+t#&jG0*Q$*A8Rb`VmF^ahH_WmEFA2V733{p^?>CzI@!TcWC$n$J!fJ2i=B{r3Z+5 z5^#N!=7bQ(gwcZJL9C=?nxGdNs~0mi<*VVvr|$=8b$tSPlCwVZX`@-1n};p@`l4&@ z;W6Lr(fIudn`LGOad7evZRPzC!gS-n!LiWwov(ItJZv##`b}xV*Js^=X}f%%D$*F$ zi$lrZviEgepHqCa_R+M-!!9Y>Yr8SXM#TU3OV>WpS=+;YzIl4!5bUuvxkPR6(>b^0 zWb##Bk3%yypR3oY%K<0_g9x}CXUq0yE9ekA>izyO!nrtOp>}4(<5Ep5RdY+rcmwnn zyUJZVKew_5Z>4_s=UPk}U$@GdYw&F9t zeRMoO-BY}LA;)T*iXu4EAyJO?!Qj`cILb2KmMjI9mgBgF1GIfQ`LvYlNz)}BR*Ym> zd-|WyqxIEFwhmHFoX}SwCXHyAzMx=ntGE=w-2DS>oNw_ujmtD&d)hdEMBP#&>#0FY zT4m`klgPB{)Hg7|zNbC?SZ3V$a>8l36RmQCi1KRT=8AlSR*@}Kz*+pV(Hr`5BSTb;-GuXAvK9vSHjam&NJV}Qt>{wr$gj>sbHFR88_ zDlMKa9WuWTiK9J{O|(|i;^X7D=8x9aKH3khsx>$)>76#f2fU_PY&#A8p(4CiNdM`S ze(>dfj@bM_gX7BI%5E}z@h^(B>uA}h5pNq48P)rm{SJHSJ^H)0LM-2vZhv*#dmf%_ z`8ItxTRb9^Fy^x!M7j0bA1n0ruJ87C%gGUlCXqxh1+&c`E7JC`Y-+Xn@*gD1vl^FZ zH0C=*5h75Nx9Xs9{K!$_`}7i{{P|-#dft$s3|`Aw&la5(PfR#ToKO)+3RJ>4uPd-e z5yLCc-J)NDe3#Ovfo}5ULCOo$*T3s*mxuc*&HIx~>U{~HCwK*S%H{@-ToeSWmz{q| z7#O|YYP*)TXdo2+ z%pLO>;UMJH;Zq%i%@$>kU&$y`eDM=rV`_~~<~*+3kFP-3t3v#8>O$K$`=>FNd?9wa zX`YzAMUzBL>k9SJhU#qYsaKdLYGj_d0d5M1P0~}10)>puvQsO0PK_Z<;#Ub5m_?Iy zkO8UKw zNjTAy*=GLreqZnXLF-5advA_NQa@^pGKxhy2-nVb{*3>#M%4YHbuxa>l#J>TY2EV6 z%QAH$sA?;(>ozN43; znLWv;2m%(U@{&DheKNiZY%~!q7=|^PWV1iZJ!;jg9^X`aQyDGQmLrMw* z%ktuS-cgA+Hw*7|X4N7YVmh4z!h=u50vPw`4`4pj#hSP8gs6${Atoz8gimN3knVtA z04gp(nK-Y_5bjYXGDw6$h-Lo)O-dNhghai$2b%2^aH}>S+6nJbE|nMnN+O?PG4Idz z7$99tyoSI#cneMq;3g`275qKO41!B27lvrw4}BLuwKIKfFx^ z5H;n`9_0ITVSte!qv;9X;amz47^p^kGJOwi{e?lEqX=NSABb2e3|IgEHfbD7t?e>q z-MUa;qbKH714h(%{7%l7bh-tSGg!-jaFntz7hF7xew23%R^6WcWe zKv38EbRsRLj}X{3`ZLHaVk0BY!)R>(5ZWSUADrTr4rsYX*J+@6+)XPxQ%IXK!#1E5 zxd~C_lW{|ZgPve;Se~m@0+A+81vO68m1aeo)id7TwQy(m1&GjNa9x7o8RHP|uM00& zT36@A{|XIbaFL0T3#IVxSAH9OeP$$p{C;iU1%S1E{E15X{yJ7rgFPXM;)_f9Au&;$ zUNJpX%Af}k_P4V_6wmrje-PW#tQecxP_C@3Y_y!tSMz+^Weor*^<$>{a+sb_W!swy>Q7HmP_)kdpA>K zC%W2~7_YeX>xp5cb-3vy|GP$eslN{=hm=t3XTeOHn%-Ro9EZ&G9&Py%$ zUVKUY2GWETNHU%1yYY&GFXlAA=!g$~xiGdo=fdzh-9*GGH23OW)rwcgcK~hU8XcvT9aQs3a3AJB?cwKK3&tdtAyq5YiVemfG6_C1KTt2Y{86b| zpdg(wl*z%X=xle^bW(bz=y#6KVLy_-IbI|h!*__!^Q-j1<=4q|fqmma|^ z45#15Q|GaiWRsr7X4BKr6+bd?7ye?{X0S;~PcM0Oc{E(CRcW%>P41@#vYC>nmG&3? zCXMg*Gd0pMw7*;bW}0egs>8azL={UHRFo$tlZMq3B_l!1RxB&sF`Ax9WmV;7>*$ur zt(G50*mUzO8#Xs5O5%daqzb{+4AaLJ$^Eh)bv+WMXWw#?RMYY2kC}RvnRJ)O^eR0X z(!P0(bn6e5CJZ>tK!1NIF9ssg7W_47o}JVne!8FTdvrpT^`XrE6-$@JGf$hrO&V8z zZl$Y>)8UofLCUFx8frGfx!AFTm2NAUQG%H^zqSE}$kkRe{*MzGFQT4s$owPqu;^r4 z*%&L>s=6|f;NuOnYdO&X=s#iUos9tM{&jbZ` zE(Fyc3nWDpYA1s5y*1}o&Nd6%!t)OlfmZL4KLs^)(D}a&rhv;ldt0{mE9he&Fv?b2493yYYW&3(yxgxH@U11~ z_f+e9eX=MlbAZ=%Ri|u2G6nKPI`t<_UFqS--rtRJS-$7JB~9u&yOvt;Asz3;p@#xx z2H69&EHOgvF=ZBC(rQ?2$vJFi5?pves=pTGQn|w*-YO2n@0L6h>dncK+YMfb~Nk=fI^WUG8qy0RfTrg&f=8S0L zIeFOautJDCA5w|6=H8Zyt$$Thj16s5VMYM`3A{QNphcr<2WZWw~heIWvSPGmr|3xj-wPs7x2Hv|tgM`e_k6kEB)Tw0gg<0v%n>dl7jPMn z*&H=rpod&dJRQz&%y=BqDhFTl-m>0PQTxv_0uEo{#o0>C>OSI4#nhRsAw;|NZ1JJJ zZ8LQ3BVd}awY|%RJv9T$GN=C~d@dH|}q$uFEiSk40Ub ztVqkSbTRlG>YZ#($ky6SDnyZRznr9G+6rKb-Y!v?j`;17icSl}The*b2 zWO%XnTT3^Ym)u4k4O?mXu}^JkrD-=K|Guiu(nl*TY`w~y`K_e7-lgNB3q6z^?^R2> zwQiHUaCIDnG*3Z+7`V|EiJ#8H&Ok$;KWV`0?Y6)P4oZDj-`&Rbf%`(5cQH~TSvQEG9!)QXonlcSBqRlP5 zAo@EB!soP}h4Z}i^AQ#SU$8+m`Fw*e1vL7xJ3^4p8DSz}FwsYPn+7{J{B-8y694KS;F??F%sbZ;IBaMr*_z z>PW(OFc=*jtXQB*JOj$@Ace+p9Q2?Mk5P(p@@X6NlxpykHE}u-0vIS4lUh3+SBYs) zkY3#Vr4WS~Y_)>%(Eh`^M&L8T$~&d|#m9LGur8%&*t`Eu%?fcJ;$&4oMf&e*Q2VFa z_b5?O{&)2v0opZ6*CS+PVv116@43T)L_sCHL;KNO zw5tZM`j2AhT1i`pq&qZ5ov5e~3M0{WW}mQ?zR6(RW^Wv>w`-BuiXc#-&AKW+2Z7ukr1%;-J#01vqaX4FP8j{=Mx}$UOyT&TMbLGOcJG!XKyuY}9-c$BaMnOS?RyK)% zX#27zFqu7HF4d&3FtL6#T+ep8N*pZMvt*L`IoFS)eJaz5AE_&z8Twthlr{Vq1Ptl> z=}=ti@m8OU@$0J#AE%dp#)2NY05#;~u%AU%FX@|t0PjB?#}Xcw%|bxZ6h}N_DF$pu zVE_WkljZ3?JLE%?N*j8Ezz#In9p8-SAZxh1nOYu9vj!NKSf=6E9vaG`@sd0U+&kGi{kQ!hbqT?YcGjrG8#UXG!Vf zD_e#mGrEik*(S~fZ#GhHCou~cXBVf}=U7xmbnr}~( zJQ_@S(UDfG*i`Ryfw8^xVtE?3(|j}tFDu*$9>EY48i{FB((tBk~ zepmv9#F^`gwbp(z69)S|U&(@kEXTMbILv8@b~+(}VAI8(g_`?FCsztrMn)zZKujf( zctlU1WwE}YAvzcJ5g=N0&0&->f6=YaU#1QJeO`%IY|!$RozxsnzBnM52_IQ)pR z90Z3-;0>|ckX_Cup#V#;egroYx(f9Z=&ct6=B`9Iy@aOFy;_i@!%T(vSjBO_D#Ed8{L(SOR|Zq73}tIXCk z@OY1m`9!Sr?^P;{C(vNMd>gkTE`ib8MJznH-+KFG&8LC_ww=>{H@=kh)F)@yPgZ z`?fE>M;{kL7r;iI(07|l+-grGQqnD5B@^&&Ao(@g-}H;ZWF0|M&#t6$<#x<%^fQqYtL)VXF@9lLad4Yzm!wuTEd4%Pxx_}0k#5JYotw$2*`4O_t7p2d8fDz#Z zOFjGIw;5y4bxpe{IM<`SAplO$HCOS2Dv-&jo<~<+mJzaU;IEG7$v#p=uEEDgdImBa zlmcW#8tdeYqiLj`Y)4Ui!XWm?LwU&$_i#f@Aic1{M(7l_66{E(C%v z>#5?TB2vC&?z%ulRJcaeb4$0gUWeW?W)E$aMe7VqeE7B_|p&6~|D%re3@9**phwmbOPlyr= zQfnaH;+d7DfnWF0N8w4`fJmd$a*5aUNL78x3^<`&Fmw{lv=ACE84QjNdo8lUKjY=q zgYO}OMQ0(3e}Mh^VUUs2dG~uPe1Jv1uBI}DY{5@oQ2M(rqu?}y(?F>1!3YjBA}p=l zZdgE%*2AgOh2IXH0*4e}k(``N3fenZ0}mKZU4KS=@jHGr6bll~WY}y(&GRIDOoeAo zp{lCt@1HPy1yiAGaBe8gqO+k%=w8Di2jVwE#96sd((!c1E4y=c4_}y6O_b?>TpP|J zckl&CAqQ09sbFu5E2Oh?9AaxNdLv^bDGF4J9y7qOW*#9*CAIA0Kq_18Uqd``)R%`{mrkjv2@c3oGhT%aJrJI=f!?UPF`8Ed+yFJNN2sJt0U4&2 zBZ0X&*Tk8~q!|rE0K}@CDgaXaY4yE2uW?usVQT}Tq%x=-yUIny|3HG5X{fdwRsmYL z6=3u5UQn6lRl{b&`Um+AM64s8hz6gXV=)p6XAhiyZ z^{2eNzvXVx&2j`w+G%FeKzwRKY%Jx8=}D8r5(HK&es$gu0qz7`7Q>gvdka})-uuFA zo(itf340~wt%tf6HrERKFWv`taUgD=$AzL75$EPeJo+_q8SCMUvp=B_P0E|!m&9B$ z@43b70zEX(yCIZLe5S1e124MucIqVdouRna3#~rZH`iCiK#8~h{tgY#6-f3nOy;#d z7p}FY-B{|)?vAwpufSJXjnU=ZnD;iX^R-@|+Z?Ra_~flf1D-d7ssreooe_K7S%7b!qrml1;#Af4KrH&pTxGc7e_n55MU6i8hTJEdI?mc=J>B(d`n z^WIg*PY?z0ar5^|J=>I}V$NMj8)l}U!X$$t zNw#b9rt-L0lZn>=)!5~F)XjaTG}znwB4}#We7)O>!+w5NZXN7$nc+W)pS|U=$&&!{ z$(R%o^(`A*ADQ88@l@iGZL>uuhfF?HL1u7w`CamLZvA8 z36&wOupRK3?XCB;c91`Oz!sgu@n7XpnU|WE02`_Ts-_D-U=adCeuHfkY_bG%ErY;U z0!$jEpE@=|ilkzx5)u+BkGA+IeFInDf#l>t z%nn)C%w|l%VI~%OKOnRN8lphYfd07X049qY=(Eo4m@V>*%Oo5NNu}(+3L=Y?(rbF@ zwPye5*K(DoPNzs_|w>I?OtKwJ@zw?7<@zAdAGF|?hXVvZ}(zgbJg zo^V);dG<~^;F*^uCqK24iQ6W$pQ;G3{#E+)x-}tEpU2`myw>*UQxeS-cbpeq|K9NU zUUJPjc9V`*nafV22>6_{*INCiQ^fiY;CNrY9tVP@NDwk+9KU8$v&CTAYJ5NMUbARX zQBmXJGXJa)1~y&_C-$3C@GFko(E5n=fiOLFH*g4{x~h&Qh#2-ThY| zisKndL2|bAUf$YMGVSqP95|w- zW@ip+w{Yj$)ngiZKtadM9Az<(LWz=N;B%rbqo~MPm8&Rtm5`Fd*}>-UJg8u)!!$j5 zJ~>J9!_M*^2tMq@pf_nCuwsn(0UWEa}za%U&=eEUcrg%YozbIfs&Sg!Ir zP<*tmCk?#hzwges=wk66_*QauTvR@z-@~-&Vv_q+ZfK8O3j$FLw)=+aAEyuU!vcw! zgK1u^+t=S8u%visF`vJysoHh%syf>q8~(FTG>K2lOEi_W74GrZ7Sc*+s%bHNx%1u0 z#1;A*I(+~Ym+_WNgDZJ;y}u+|M$VZ=tW_9l<82182^>TiZ;^H%kddJ^R2VPm0=u8U zZ>@;wz{mTdi;&s8#YgE*&iL|S77@9sAp&kDtZ9=vZgju;>m^2oZ+aw|&+&+qMN~67 zTmT5by>-EkXFqRC`Fgl<=5T-)a3mnSuDhSGNO?c_2B#upJjVHv{=r$8cCpBRPDueA z+Jhi4(VmkX$*q4eX{5O6sW1;f2fUE;bQDmTbrSNR^i7uKFRnj8hBjpg8!JFD2pgr#7J%ppl=XQtNb`VuOPR%tW& z+^PSiy;7hg1#5ymA_et>ThIoNQ-KH0wcIlFYtw)35qu54q1htY7UEg`i~k*GRKm=G z%sMrnoL2jk?`1dmTiDTL-k0zhl=~{Ku60Di)=Sg2p#1(DD@pblM6!6_i{A^QKozsX z6oJ{q7z6|i%-lDN3OeooC#0%x82-o^lP~{K;?^eu3iihgcJ*=CV1i45U}JM=S;BB{Yt zHc4P#la3-{lc<~@MSqE%2S}Lk1t7q&_yYNZi62J^sIqFo3;ys3Y8Dpx4M6A+^En#i zv<4MB-v59#VEV=G2g}xAedC6}u*HyD+vZ=c;rz?2CU=J^E&-45>G+w>Hs1%WjJWLMNF8LjNnHsx)kivDqy4aGUe89| zZNU}dJ&-`MqYxUewb4xDa-?E5Xij;;X(y-CI0C34#6jRcG)GHIPLCP}OD;96&^xsE zcO)k_@k>~;pI>v$cK`mUGsy7rdq8=Q*JxPt0Sc5{QzkS`b_%F#*=L&v%iX)u($aB? zFuFoNIV}0>gu2U|IXhde7N}`Dwao$v5wqj`=lt9x%mXOcQ4xiW3}*zaXKJ1TvMUt^ z`4cq_DEYT?BO@`CKLODVPmo%A9(zsjV-|Q4yj zYoDukft;uWdXT3js)dSK0-fmLmY+)DFlndS{QQ6hC@6p3ZPwR2^m#|{4b1hZd^l@X zbtEe%ms?ZA4)j%I{YIzv_sQxMO_@b@jBS`t)N?r1-C{5cIAy0S-R;S=3#tlVk7RdN zTO_Ho`1Ef>M^|N?Tg;D>Vr*v94bUek(jUS@CE?-iciv&gBmm%yWh*9(OF@PD?mgUI zH=uL$u(+-AO7QUT{_Mxa5|L{GgptaqTUS~PMBXR-o;6FfAs@Y=%=%x|Ccfxu`kH!L z>27FO4f7jb`v@F#;yX3S4(m*K?X}Q*JVq%Sz^GjXW+_dbqW(;lJwoC&fRO$p1{8%$ z01aAn&kPh_CX7feGcFk5)>5EKG{yOyu6Ka7% zj)O`M?>k-yOk>JN#K+sR-+O;Nw*?ts#A-$z`w|24%XPWPJ&N_#ALB0w`PJHKIOTB8 zTjt%N&6TUak1BNVu$f0ZOo-wk8dvK!NyJa(wJmC+0{6L>X)UdBln;S}yA;>qQklBG zw5?mGOH$XPF=L9z@7mRI2~g2E#E8dB%&-bwuTpU5Y~WEJ=c^|^zOubLohi^vKprYO zr9jt&At>NpWI>$Gep|7=mFKkhM*(vF0#OGhz-n$ZstQTnGU4#RvyF*E5ZD+5M^M4L z39ka^r9UwswqBo6)*&E%@+b9=eg+bfhzzI|BU-+G_+=R&KTw@f0mW0tAQva|(ch7ZKc@ z-%*r1Ly@9r<8uQQ_^(&S^21{+La`8Zi$VHNsK%&jO|G^ud)H$XtY^}G&=_LQXairU zIl3i3B3;p`(l6H)elasWQq9)br*uy60hhQyEs(p$6WZ28JnXObJlSLipVl<+rJ8n9eh$D`e(7FW0GMyjsHc`vi!wjAdZ%0ZRO{g>Rji4sQOMI#t{BL{OG~ZOqJ2BwO$MJBz9@KKnMC9w*AeNsm24T~{ z%pNf5;koNde+uDr;%{O_Y5_xprx$?IkcJfnuUkhi`VFtCnj3esJU5@(Jj~}$d9|Dx zqYvdDBNg<$bg4ynm|)pBkO;*l;rdWjT`dp&^6r5|@J=LbG%qM_XI}aHDO5@_=)qCS;CxAD;)@4hh>p&v%@n@i46o4a^ zGpZGSqLWLZFivJMEOYKIt+QV!bKRc$TtlS{x+(}M0GF>qE0e&w#~oANcCB;CWox+M zJ_>lff*w}uafX9suOUld`lre%ch2-aly+J0Ih9V25xmwi+n8@@nq>h2aYJF4jp_Hx zDaWd#F?55&%$Mfjy`{iOB*WxX3oO$B#aHS%&AR@!mBDsO&~M}pOtdURJeH?0=N#o+ z))`~F1eo>{AaWDQ_zJ1S!wX@adsI7vAS-H;-n83wm!JFKslP)3D24qjHp}SIpywPw z)s_w+@_O=xMjdRN@m_rT3E<>Xk0Ikv(D;QnP&PONh4yFtrn+&($U%vOF%I#%Ib>RP z0B(5hQ`v^{?;Pq?nT1`po}CUzVCSoU(W&jU)09BNX-_V1rSUJM#9VGzd;1{tgNnEb zCH-PahFk^@M+}utyJCEhV13&nXFHpwDJqRTD!~=UktLK+9$Q8k&q?OGBea*bw(JK0PoAcVnZN17Wz7dn z%w&%pNrqVH>ANvZl0z~KS)p$&03EOP423vn0MPiVo*bgc*vp^Wwhzr38zcGtn*A@V zg)#(jf3<`Kjlx1wSza9gG)0<#?bq0Jk6NZ6QhMGtU~aY>(Gl{V?|0ME!dN5FYaNgT{u z353pAgF}w=+_91V{sbWM{0rxNGbL22H+8o8XL~d@6yA3_PnD~T^?r)kPtQ(xa`=*g~KOiT~^3Zq_FQD##(U36;)|jNouD z0)Cv*tUwk=B_7deMavHtHC_q$i zr#912;Iml`B6{%f8AVH^j3*0+BH9@R3R86NP0BOl`kM-UiDjTBJ>61EBC%#PY;6Vv z1YYSl5R7Ox974WVE48G{yKemH9slvokjJwzI$tphbO$8r0v5y^dA810_wW~B*1ko@ zXDq-vyZ~oO*vePEq+oln+;#lZA3pbVNoo%|x^Q#tb`HH9&P^_q-m9ERI7>@TT<4gy zsWa-|WofZ_`uq3gL>NcbWx@jEd;LtlP&rxI93nQ09^pLDAC@>eHuhyi-m7nuU~{Yh zyE1UOLmOcAIBb-P{*Iwx!)sujdU~)Iidp}lj8m~A1WDVj1)DjBqOwgtb9)#;{+jtv zn8W8^Kt|_O;s|PoW{VoL?ZoC9PZL=!k2O1v}Hy*`rUuO7Ug0Gqg@YM{>+B|_NN6$z5J@Mu>c^Y4iasFsco@f!i zLSDPh(dY4Ic)#kmQ#(oXHFKxen0TJ$pT%Y3w@35}{X_OZLY2v)OTOv^c}9IBAUd_h z;Fnq(bkM#t<}_~)^u_1_pzA+l!dy?UXv0-^!PG>rY2%sco1Q6PRaOHrwRw&&N4ymJ z%lm9z6Xebly7fch!p3=Y8(hv5^Vd+$X~i~!Y_+@R;5D>1VP zE7DgMCDSohl3Ee_ha{rz&Ebn&@V*);S@6GNut&ky(^xz}uL!;D?Bz0cJrRRp{RHYC zSj8Fen6AQf9c%MvCBlYflC)q+hCQC0IuN;r+$N|3q;MSiRg`J^!ubFuJd}iKU->3L z`+924`NoCkx-gcQLW>F2)eY|__VmY?>IPL27&2b8fbb!#Y5w>szRo3ZB_|+|j z4ERgEXuH-QV{j0`TN+ZH{*36KcSdduOc?@)|E|z(8=m}NyW#NUl?a-bJVj6;HDFs@ z)R6;(ftj9(;2|c_!NuV%bZf=y(Z@7bq zF)do{N(p-qZ|M|=ImEMJmDy7FMx*E~*R>P3dXlTw-86~L3Vb16G+q-kI0#a(|6JRX zM!?GeFHOpfgfI*W!_cr01lV%`)c?;hQwVd1htrJSyY>U%U{XFXxTyO#;|x#&XAf3@ zWF3W4`z^-tg^G3D@G}Fu}5B#ND-`e>@8~C@_`_G(y_x zSA;a|Kj@o$p9qPCt$e#JBFu+7Q)T|37MSS)kR6?7v-}GTocYv}(Ld80-@-V)1kE-5OH)(OO25w{?-^P>`E3dB5DEu<#JGH#-ZyW7!dSK4Up@Z) z{R3GY&^YRRw!fseVPR%=cCrFj>W$e^y$Z5-Z`CUn+apWBTP3h_NGH_+Y%SBwHz+#_ zU{x+yAZay&nSZO6xjS`RwJN+cME2Po{-8{spFv}q2ZH7Z=ZSq|JebD2l_0*91)=oA#vE5n(e}MSLqoF$ z!QS`EiFP-exOs_@N|eM5PX+>*z=XUtw)6H7<74~2isjp0oih5xv#M&?ZRjK4)!;9| zdywyLN`e`V4JZjj_#75ADjBUn9zb%aFw*EypaGJj$6EZe5Ct7tXO~%#^4~(5{icPh zp@LaEqQP?l95N6KqVa!Tj79ewp)Q_fvbd#9m9rHiXc{6mWIX0#P6&pB!*_u_3xI6_ zX3s|pewBcN1|t%haU3FszExEx_XWiBqWz6esxkTof%O*iBE3_CMHn0kc)*#%_k|fz z7~z5HI5FL|Zpi<|5ywG0Q0Q@x5Lu6+0%Zb28_|rA(?6o@f@5aGIFI8ABAQ=_TJXae zyp!G?n4fMb0(M*&O`KrO&hcp7?BtgMkK3+XZ*Q+!wiwzvq9}~1P!@03HCz^hCs{ah z>F;HuU!)#xN1Lj}_w8n5GIV3rYj{w2>YvD@@^gEv74UU8NH1{jkoP_%b>JSAY=%iLVup5I3!$CkS zT_wgHxa-FO^C^Rk`u{VL{wb|YuTi9V`~_%a=W7IeCqm$CF^F&Xv-4kou?U%U5 z!#RC#8f*!!K00~=AAL6z1Mu(x&n`T&ZtZG|5pbt=#5csKDQ0pBgU;#C;8_4a0gbRj zO^|+P@s$6|F=eCf@WjUOg zsJ#vP7XMrW1E3n{KbfhvjG1IFkk3*W+^u<5lwx@U>$t&xCR*+BNK?5Ve0ZEH>6MGrOIWGmO`@{=SCIPh@ z9Z;5>ifP-dfY|Z;Ga^|CW)u-v``mF)_P6A-evmfIh1z8oVOp~D_9d4PXr*!dFK_tt z4FPAK$KFh%Y*Gtg*QH^t$zZJX@cXws9#Wz|8B+VZ)OO&TOtcfU24Q{^;Ocr9cbdlI zQv64!+Cn~$FgFb-^2Na2`CJV18lEEBhdXr`{m6bgWe;)2n*Bo?rXr>$2m{i(R;zt&vIv24X^{k z9I_K7nlZrH_hY1IND-pdYVsvRD;x{77Yd=G!L%(s=*)}N8!P5ei=GdZ$AULUg0KdF zShAnexY}s1fL{<0CWA4V#wwt}f)S|Spw^ZLE|#R#CEneJAf385PcPcRvjFm6+5Z0X zty9Jg!J-i`RJQO`CShn!q71e<(_kdvBPba&^H3y#UKW2$$ke^UPA ztHf0+1BJcmYI@LFC6zq`C9(po^WbJfifykY8#m80?EP3^q{d#criWEt%aR#d zBZr^MRPtncLstHm0mk`{$!MBO1%fI8VM>^*XAbC72Fiu4v7MSQ~n+N{Z(2oKe1xchJDU!cGt0be32 z+MS2YkV#&#tKV0tRYRoW4j2+3LdvF(PV(I!K#UUZsAo7tJ~UvI6FKnIc(8jH=+IvV za1}i0-r75d`_S0E^%VP}qw`e&a3zicC>FpRI%S8oUw9o#=}zpfsN$W#`=>P;)a z-AmKF+M7EJ3X?wv8Y%$^EE?%mZUfh|JJ6~Ag|38u)3{~vw1u2t_T?eFTY6q?1e8>mDePg`k_ ze8d`ap&ryJwg=C{-`^0l<=z%7VuS%kzGE*cx8ID<18vZBElT^_^MJ>Z4pA8JW#k>5 zDoyNtkxZylxS>C;nWh%llQMR6;4bg44h067WCt9f^!=p#NkJXO%d>y~oSpzy&>D@2 zphg2Q@9kA`1z+F!+m3y^>HvBRfieq2Db~yZ@!m7|OR_1a#MO@&j$GG57UYKBgn7Mdkqe9Pq$N1N4{=JnLz8nMwb#@k1I- zmR!RZ;CUB6W18H&cs`y2(k2ghkYE6q_6n#HBOvw4-6(0pY=^(Pkwg-o!wN`L@&Itx z^z6BsZc1dOK7+nNtF@X726>P^3wWi*07f0yzii?Zm_1c5(@O=nq9l0S&x?+CGk6bI ziT|%=&O99IeUIZv(V?bDMY7Aa?IIDk`_@I(Q@U8;;;ckY$zdfS;vG%HqY~ZHtmS+dm(C8!+PoAOQ zU=;;vDCvR%3#6_nv@>Q2ti7Xu%QD1F;(mwU@so$Z2L~mSG^@d?TaQm2(0{kF2gpW? zZ5+J+1E}_S6uGfB^y21(Jz`8u0!A2oEB-YQkhYd2lE*k7JJa3n$13x>a!9PBx{$=n&Ep1?MiCl z-rkSGhvW7kBRpRwC@820aCkcS_61101wvHjQ`6tWE~>l^M8Yo#V#=cgm=j`2#`MtF zN5@LRG;@Yjhwix=DdYZ>C2hhwF5icxzGf3z91zO7{Z~oja_8_nMa3R9>Q^VDi69q{ z`xoVo|Kq2jN!jd{Md-D$HnRH>Bl#tZ>P|>;i$*j^{ybqnTr=%%>rz zsXIN``fnA^g^uzev(vAz1Q(&Cl8Rosy?0;gmiM)h8`#;8(lOjqM%rKBA2b9TE2}{1 zR4xQ_nTZXqv$nnEZiABDKz?2vBKufkF<|Cap$D`szbRLoguBRx<5kkWay*uAE)xH3 zjGEE_A?d=C%Q8syRqN>zm%DFnz&b|BzcOAdp}}VSJhwfE8#0a?ZP}e8CV2XZiK1`v zR*}6VnO!6oPR|nu*{6=r1&rtGwshSw@Q`C2@H+%;IS{)jfSt%T{pNUE?%G_f=X9?Y zZ43%B5@>|gt5@T(Hsj9Gpce?G<>(&%9#fUC!<_9ESGGy7MDwp?ZI>0^5f8cgu?Tbj zFQYJKax?FKRPvn>SFz6nXNXxQGp7~Q+%%44Lk2kr63f`Qjvsq&JKh7RREf zuDBs8<*7{Py9KnYiPu)9&;;%q{A-p{+(6k-RZ~lNx~V^exF^%wdYonO;rhI(p4)Wa zV!&q=YqS++;wV^@u(q~#p??lTti^M+R}T^G2VpMi`1S&N;2nqbS$Q(2&kjJyBtOvw zC6l*D%jtvvftO7P5?^O15dM;k&+4jk`D27T5&;Hwu4!6xpQn^te_L1( zCN582>wRjy2{v8@ji-x$f%oWnUlT^NM$`&)qVagtpGv1rrEn@0zc926iKbkb za2W~ZMjBNh1X*sgnv)eEh$MOOx|XkFl0^x}M|n`ib@5I++jxg8V?@taxB6Bdb?}lzUGe>2KiBPq0VvH+ zGn+R|MpmXUB97B}(ppPxB2Zr%*TjsyNl;LdKBSqEh&s-l@sCVRef+_V-3FT>ql`QV z^rnqlwgNMrPLveY64`ItA{tA5q_S~Ad+g#w$G_E$AcNLq9bJACowq+F9k@b8yW1VY zx8mAq#%by4mdoq2)JB(0G(=l!banVlGd&OOz7(O*;hDW~J!2ptaFV&l>>Mt%XgTc! z+Jvt@whHk!cRI|Y?%l8DD3iwSp>D8yn*gS=Mj3NRZznP+Ld0s_hH^YwMJvJq%H23& z#D`yBr>kFwlXF-hfb-;W*|l)9oYUi|_Uo@oMjHRP(3D7S7Qf%!2A^DMr{2WC_U@Tj zdHz`}c~Q(X1IQ4S5p#o*s<^kf0fVLBZpqt6|NQvXTrHx^j$5@p`Nd$YW3OGB2X z%iGnT2~teLvP4QuLW*CcU&T=Umx zRq?*$^Eeg_wYLGbwsi|RskIWX$nO6>bSrzAG5bsh)+ev=@2xWg`5%2IEYjccodKK6 z6QAIJPRu$oc#`shn<_Lh4Ky9AK!qdUmpf2l9H2YKRFMe#5^_b85cWmQUg=*N3J-*f zRUhK6&5d-|X@S7#g3A$61|0^%6Po-zf0VD2jfA7>7R6O3xo6EVo`f?g?BNP_U1d&` zlPCT}_N!WkoIJciSKxU^=#SA_+*_H*Lo4!(o3NI& zAkmu2^R-6~E5%C*uxpZrg6nQGwuQKOtgK;TErWk^^67MPAc+Znuzcvs_U5!<+DW{* zkmlnWh1|0pt$oj>%$k0D)7{FBK=_6O>!+CEL%+DR!Od2FWJ)PZ=7X2@3H#&47G5#` E1eUxUYybcN diff --git a/docs/interfaces/lite/pics/deposit.png b/docs/interfaces/lite/pics/deposit.png deleted file mode 100644 index 1fb3acdc5aa28416ea79ee8b6e155f6a7c497c41..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20738 zcmdqJbyQW++cioFC=G(Nq$o(Yq;w+D*8rRRFvY4gRLpV$^;JXdAN~*0loCg=bi7~85nf-F}!%>;G*pBAFOQ9 z)Y{zF+)B}A@QVT(r=zn#h`rG2gXdY--i-Q#dFx}Z%+ZzGNM?oS4FOkCyn{OJtLhV9 zco!K9dp1NwYLu|#B;}+eG~+e6saIVO#A$_3(J8d6>eJ!c1mTT?9>bHN8qdR*j8JZ4 zQ8?qq^|c|W>>(yAzX>l$>dMc>@(6T-ZImyJQ40w zCyiXgo58{-{QXyC!V_Y22Ndic7FU*Pmgg*S?1U_uZ0l@1G3n}2K966mJy9hv$ux_4 z&VwMzrPjhLRFzszQz0eU!p^LvDB054JP4PL`Pd9QO$fzT-s~~oH|!q$&Srz0-sa|+ zPuQ{v?ajqrScsq6UVM)0=0`^UV2SK!z4iz<2=@=B*;TuUzkZUb71FyS9#)p(xy#$z zGGau;OB!UqCcN9*+lKYq+omAjQ^cihVN5t07sx`eB`y{moG_fU*lSf+_?_g3QIEwd z{}v5?d|65@+v?v*wQr0!Xd5PPV66F7UKI(+cS%LeWKc?<5tqa3UOTn=2{?oA!{-+^s0g z&u|D7_n(DWVe%&4FnA8O8u{O56v7BB3Gg39xb6-DkL@$m#`&KU!sGf3p<_QT_5F98;Ae&R z=Yq#Z4TB3d^+^rG_%{{<4ttFIbNLASAQ^BVB7L#?H)^=F0L%OF!XY8hz@-sUJU2%C zcN{`_9mIc|VN<{p_QAcTB>6XHaB0N<-(T9Vr@pt>^S2pWg>_6Fd3Jw(s(u%FU@_k) zP@vcF%Cs4skfqsb%kPB5p`3x1_KSMK+vp{J1s`F49G{`!tT_p7QIUn2n)iETT_L^=#T$~IRDX8JO`wEMp(uk!Ks3IUR(b?@a{8bJi z=6uf19;uN0N_=a)AWgvIwDX{BKv4E%Ya%OCKC!ko+GWm-E}7p=dHPMRXa&Q+^V{!^4Z_3eC*#Pv(;qY^affASR~CwS0Uq7C|f9dqwKD--7af znSFDxUFG`px2@?10lw4tD$No@i=)*(Q$2wmj-x{TD!u;s_X7f}ylI#>9K(G-!5k-H zH_NGfgF~eV(?*y^O%TV*Ad5I__C?%?)&CGqG{ru^FWM8sn1(|wF?cee&rIS^?y=2U z7L3E|ahjk1?Zd@JR#bTS>!PNcSF|)VgJ3ZzOuOO@5c1Z8QE+%&I0nShs|DU%?|IA4 zy>i;@tV#KB5kT&~P8pEGWB)NzA({RFlkC;t?rfbjiE4OD-AA`;wihp?hrJpaUahLd zvyyDof4Dq1OBu1|v|(5HgNL*jB%Cxuni@}m&EYF-nlPOK>2K3>Tfuia+kcm#Tjii2 z6cJINuu~X)H0?@nJxJ3R2ia7TY&c&{oH}&b9PNs_9t$j@DR5Znc2FQu&6v$Iy+M1z zlufUe8+YDxxyu(_OE<=EGnnc-T<3+qwzR)fHBWDy)OSdFz%{ablqM0vwj!6pm8?kV zBRqrKEXUrs8$LLVjmP7CQ~yG#PT54GfR$mU)FddM?{J#BX*^$x+Rbe#%sD7wB^b5n z>08mrXY#$Rd){YIOmcpyt1}c7Yov`(zFn4)qqPCW2KN)TZ*EnVE7}YyW4UT8q(%Cb zmJ^{eF)yVF%kNn7(Cg&IzP(MYjAIe zESkxkyo}Uy-=NJ^Zy@%%I_NMZhMndHMBNLs&!iL!(QpHVRW`Hq5UW&IQ_XZK9QHjt zMgG^*Usq1X(j>9iQ*fqkj|L=E1;3FCSdeeY^QjhYtBFE5$0eR|4NI_~+w>)HO4nIH zmfAx~>tf8}{X(sTQLxD6wBofSSUo?&p`KB~rEQ>KN4#!+;yaWknOG)t^9~VuUGjSr z6)IHHk!XI#D|PdLGEaM=^Y#YiDWTH&)z#5JpON#g7{!;0-1DAgNk%SPf9JhzGxcj7 z13-W=B?kjeaNeDHk@%V1Z5e0kxb>nm=&UoGx=qNq*_RuQjK{V4LzK>#jTb}B6v>M-J*|QbFFS^`}YEcwgs$E|>2~HC_|%H@W_dysvHhPS*w;OHgnVq5RqI&+?Si)zq$cGp%I*DHOljOiFSZKb<}s1prre%Cb$Tf< zi(N$SeRV*}R$y{W{nAuVzs}4ptDpkC!>m6E5+jO)v>4E=))aK}i~?lCGrBja!tldF zdcs$hg8ZL6KsYGFUvv_KY8@U$@CPj=7t~8jk?_5(aiG0!y8U}wy26cl{EfO(E+VCA z*<1M!Syg>cgqCNC z{KrJ&<=2!G2@2;uDllZ8SUA&!{v8tYd#JF$0?+~G7Irq`9dcOE0ssDQziN&+YJL?a zy9Wq39wpf&)}fOdyMZaH=Zq`K}6F0LbAoW zaBXZckFhA>bx0^bKUAVv5JqV6?Dzv6BkLS_PyJG_K5n`kVnph9&8|5iJc%#zUuqBP$++#l*2c$y zCvQfc$>)d#;2v5Gr#}QBaJqM3K$Do691T24qO)}_S^8Ml7OM}PXe=byM==7N+(5ke zVcT>)ZnYZEZe|W(T$|s<$bcZ{0JC;wFfo^v6!(nXCpRWloW{-_k*}C!&nYQ=8#S*U zSWlIHxj8BF9skiKW245gY;I}#U%%-c@8-#M%Og{HU z9nMywu3=p>qL#aKCB6pHz1*k+GvSpJ{my(-$}YqWOSj&2s1tWsv4dFt=HRa{B1(5M z;=Dk))s(UUVZmA*9&)D(1*gSmYR&sK8C;TxKzs(}SSDQ>Ymka1a5TIR(L6nLa3sHMygHP9<*E|EE znVz${OZ+%i9A9~^(&*{N>2_$$>2Ye6fuiShHEExr80S#!Pt>sR zScYt@SST0N;&-LB%z)jQzV>JsrRXSt$zwSxSq`Ir+&&(WFx$RzTg6(jXPGJAddsL; zES$SHRhH%c=gX7P=?cp);_B)#7uSF1)qD{ij4BFUr&rp}7nY-eYNA5s&~~O;37=k7 zDwNxH?&Ud83vty_w_DH?=0b2wT9t}k&u2@efI2~DL#w2_J}I6tCE0V}!w9={hFR2R zcQgZ)=sa9DIEk#zJinCpf$xojzn*QwNsJEKix)3)K|vF^Rhp-W^kCmq=gAe(h9x!J zN!SACSJuGL%-@*dJ!!+~Km;pdJe2$F2lz>_gI#&o(M= zas2oNJ_9@@Cm#5iRiWl4^7>rg>m<6|Xr()Pv_w?0_Nbrl7j13`(LoKsn*lvBzY8&_ z4r=L&+@R<0GfzQGxLC$U)kyi`^fQU~y%dSVFmghz^Nvi0OzaO7a#!Jt@SX=$^XpYm ztkd+~Ub(j=hF?^9joQ&`Z*MMXZM>GWR^+*7#S{h4({<21pLCb)BRqJ7teT=mun1sV zKSeXUIC&i!K2sFK7gzlUwmRsN{s}|NoZPm8Ydx{dBN*ql*i9z@B0_Gi&KKR6D)`9J zc}aQfgmo&~7g@ZSv`Rl?f?~kY>#IlrJ}xb}tnIe@f|ER#-$khOOlm!9zh5}FT1jH5 zco4zxvgi4sl7jiEp7o3*ky;f8y zW{4+!-1D7%$aFN{6l12&Yn`^%7g|20&tgV#+v=4CSNRJS&UF*6O`+?%q!zBt8e5V|=tidTB?Hqe~-@vOE4Sr2V!7ZUIETlc@N15OdiRlgNn zZJcP1B)Qw?@-5B|w@#rD;80eCrp5GUDh+!W7C#n77WF{9i9m3N=0)$VGH8&57}Np4qus^-YppuBUzL zUN&fxrItGhCFiAInN;7WrZ3R0de#_kTBM=*vFgjvOwvgA1GQl8{dHX>84~ym_%2fd zfis4kpLo3W@Wz9wuVn_LqPb#nZDwmrH-2S*=C0;29~9>D-Cv~?s0*W+d-F3f_~XO; zx`Ri?lstq}H;2eQI~!Rk>eH?-8X`Fp%^M;$Axp;4CCBTyz+t9G87_Evpw7+%rFhU93T@{bOMORsm+1@(gu?cC zZa%-oTXK3$T}*=KEn+>`Y{pT9F^B?Rg|o01RH;;`%s08`+BRD@z<(5cj)s|U#iOsI zk^kAwAy9Iv#6dTejAB6oA-ovz5AiMQ$fyP>2?n)6CM2wx4$ptJ!j~NG?m%d!2{v1t z>u7fX84lqc6}J6ftGH?SlK=2p&HyvNlMH@zkAe-q0OBnFm}VOOZU^lDXTJ)IJSQ>q z%4CdkFw!Nc{^gF9=0$-mgk#W+!evtot<5}}zrFeE-}jT4(@Kn1CZ_tC*L!WA z(HV!lj*6%tV}0EqXw3_fK1*uuiy!EyVv)kx9c5C%jJ}>7t%e+;vr0Bs0wCJenP%Zp8qpS3PeKC@BF?cIx+7Hr90DfILR85we2Ed?Yn15wIbDR2k)+PA z643AFG>i|-c+HZZ^8I1$VdN(!ADKMz-5@&2;Q6!S`D~s)xW55kkyu88TNNZD@6YNW z3AT2bL7;b9Y46-?z6VZMvCup}IOs|p| zT>rMxO8WBeUTk@JImhNm*0;9b()6(a~;&|HC~23B6w+z&-gMpzLGiKd1pV%qq5uXjxIhB6UKsuV$}+H zZpPKpslgCUUmU9_z@thSPX%@CKUjYrEjf0~2ni-;Hw~_J+=zHv?^-g9ECY&r`JKrU z(L;gD?J}y%H`A0E7~hB6l|c!wZ5;YkXzry(xw#TxR@pK_!gJqNZ z+OXeSV?s6zlYe;0h}85FMlX#D8Fyk=xa{dw*v<>4)DmBqe<~`}srdn;Z^}Xvxoy=S zJbK*u>~dV&_T=}6I_F{*zS%OhReOU84RS4eRM^6Rzq@O{i66{F?VFW<;&fP+8Y_M$ zs`8MF9^e)+pR z#ma->6&NlofnRZ-k}@?hiC=kd#4++gI`YuDw(+o=L1rMP&%HVX@T0L@(?s%oU~(4% z4LIay{9#48k54k0f4Y02-GBu}LhN6_lDr$17?xZ9W$0Yzz+<=IQ>`#{4XKZLsU_mB z{$gX>ol$c=*RssGE5dQP6X%ut@$-X=bWYV=)c`;ziUArXt;DEf7{+Y@ti4#PTW%iC zY1w?h?{@gc@QYZNZI-3Gd+pS-{$A@*i4j`?XExC(%seV*FO$BnJg^5BNwoQeQ4m9L zCfQ_Ln;5I)+_wE_~o@oAhwCPj;HIj~r3- zaq=rCnMG%|q6{*9&x0>oPwpZHwjxqt=rohH6DajwaB@aJQ-sRJGV5moZVb=1^Uok4 z-3*Olj}>rDOiYI=pH?XWX6=QEX<)h~H=V%As7m_8vjDTyt6>{W7-WQiqeLYoy=0q` z+V4I5uGe6G9=KA9^ECu>KsD&`3o2%u^@A8@eZlEQFFweVVo8~PQ9j+Lp8Ky~x$aZQ zCvZp~yX{m=EXQTcIP@^4PjGBB-Ci?af7o>yE;Olmy}-d2e>43q%L5Q@sD6fs6*rnx+boSQUGVMWhr7j2)mQ%C1D+lhJcZu?8u!!BFTGGC10I2Z1wyb-%)_<<53U$K&KYa= znX++rbPYzKZd?nE+6wYE5X2WFeN<-3K$P|j;6LhRKL%IXu{O3Cp?*}BcJ-10hzelp z>ER~``!sjpxGQ^pgT&b|BxDk2trAA^8#x)42bx3S#yNJ@DHtgbSmNN{i97@P8X*Np zM;q3rc!=9ZKORDn@x1WyW&1gqt4!IO3DQYi|+%NDrT50ERxTSy@Q4Y z&lPvoihMPnhziR{*vznu6AQ(B$9HlY`_sTLj7|(FY}H?V7@P-6nMnq2c-MX`KDGSI z*(#>bo0XFK5VZ{#J}a0JTvEyCfjQcJ>hyTnEU-1#_-XY%%i%l&%G$eyY|J}BuDJn8 z=N(7#p=YQ^9j`+|S`k$TF{dw(t?pA1k>V5N=|^|@@4r)e|M!F+7{u8-#IL%XT$^Hb zMG8qguRFexl?`D_gJIavVDFUtGFW|-26-N&h`leF`Y$Qol>QQT2bH<`>Gl+SmD6%( z`0=nT^AG@$FNpc@LoN{2&xqNPd)A2aL=Ol7%S}X07GQeydf|9uL^xa)A&7wS2iSJ4 z^tj?lkn{D#9Dx~Rd0oS?Z=WN*}1ToDm78fQXqq=Olo=RApo4x(Ob>dM$@b3 zO9B1rJ1(uvV7^wFdFutnC}2@|3zgE4`;z%4R9yi1qME19D9xZ-%Yi}2B0PNd*G>`2 z|H2_tF_CF)dpQol>9d&zc)-%UZ;nzNFL$a`3=OFS&X*%i3G^K_tNzY;C>|#BzV`#= zf}(Bxfgh=Uy=yq2RwU|N_PAE;KF`V_qF|=8nRIvNne@bzd*6Ow|5jAX^GTO@fZpx2 z&FOS^Hj#~;T|Ry+Pb2GzzUL7CX|OTrKGPwt9Q&pA(MoIWTF>)Rn)BiB zlHbUW7d~Mn{3>HBOZU?EzOI<((%$-p{8R-ZMk?EEV-=7+e1YKPIVen8ME&^clTT42 zU_<<2Y9Ej%t40A*h`P~cRjamp2S{yQz(tAM*HDW3WjA>I%>}|`4j}Mz0MQ~f_bccL zgSFfkD3L}%!LJ6B)Net&jh2+ti3JI$N)zk6-K@PLJ8fu73OWJb+sgZ=bVL>@7q?lRB$8 z&~dH0L{Q(0^WD$Sq{zkqG;PjIz0VwyyQGy*NCN3y;@9-ezwFK+aHQm}{#@G1QT?TU zAy6>$CN=GfiRJltBc={b2?Igo?Bnl2-b?!?sO;1hlp{OJ$9;0H@EfqEq7_z7b!>7MvNsKs^l7;xBi5 z7R_?odA*JJa>93Mamko7n1zwHguA(vuUV3o}MgO^i$PvHH;RR?COFZZQ|6)g@kb{>J7Jl-Ciy?pZhrZCCAJ@-4;QL zL}5y-m1zyY7nL>dWgTj(i9)iFG53KKA^n-}+pktm_%WTGrZQOdota5|b+w@NAshpW z&UGIEeLD)$l$CVHG1KxV6s!nnU*g)10naiNA%Pj3y zQkFvUkIcS=)$Dh+n|itWO^xN>o`$=vL~CR#rU;g1nrlpyLqrWy}ptj}!fK4@A*atoNy;6}U zq~n<{hmFMyj3ueO?^n;Rn&$S$$>WamsMQS4(;{RQo6?k-=`o<-DPAN(CBcW%9wOu1 z7@Eg2ZdCjvjo$aeZ77tM-lLJ80|ZB8-}4vjD(h`sc%@UB00Bm{e|u5P+UUCRqw|k% zika8+j;ynTgQ~^*pDCm}?dgE43usv;(gQJe{S%g8Di~P!iD`4TAwWN)6_y%?OU;SS zfiV1|P?gui6k;o=tfB%rT<$7;XLh_k6crO=sw$o0bxOo4Y3plNKZ6V?odnHLJ(p-n zC7xLY6ooYsLG%trZpA?dff;CSAR{i=E-C1J>gXq56R=dD?I9BiW{{4;>pgnSheGz2pglLP+QoDB)loqbIm!4gf4Vb7r{)>mgN5+$U8R%y2^6IHfv1OUrwX>U6 z9BkD(d)^Ga1!ohqY+<))mX$ad-iCaMiEbjkLlM4pR7OV8QU}6 zAWp>Wu`G!9TR)MkOj6lJrv7a)3gka*1q63}#A^VbLW>bu68>y&@I-}>B=KxJau6Yj zh&BI~=iXylGxI)IdPXM)U4UXJnTev`VH08VhlI$H-j|avTJYKBvzkAW-(!?N)CS3r zS3?F4J**?>`nRHN_ggce@{AccsO+=5*Q~#J42o=^3!&bDCeLTLV<~u_7)%q!U)14I zie%*>4Qgm;QNTt=3V-7T(MKMEUFkRnQ4F55{DX<>gLo1z{FLiZAWuI>-M8((NO<=O zunpT9fX@j09%28sC2hAJa#cPfQMamnbH3X*X^9p>{td?itc!4^OT=SG5&c3%LXT0qGX47UZ=#I# z9dlp-sGO)&Vor-eU{gYrS<<2%UP69Ik-Hri*;0x>~cjwuI>qw=pn{2bX>CWj9|n&7Zs6a&v)3@MP0U_uauTTw>H z)Z-zPP$KPesymNcVRHg5-|1jcoD)!?zfL7cDoG1|ml%Cbhw%gv&d+zkhLLp`b!%0LAix-+OhiQF zz@*>kxtVC&sH9zK749JFhpy!DcUKKO$!ZVK2mr(@z~v?3ws}l;##3e8`#t}YLh*^j zy}0QQFgqGS_7Cx(+;D2i!0_(wZZ=LS85!J97SKUhiO(SL8;tB_9;m`hOBgf?vw>uB z&XMr&;X@c`0DdA-RhWDgvI=(ZE#Dl=%L68?I0^QhSPp4E;C>k{Qx7=8XbxQIiH5cW z{^_?S>60NNwEyBkfHn*beY8fNR+RLcd$3mv31~TzK!(Zys80oyy;3B!Z$Wwf+zq&$ z?8izi$6XnL^l)qywml3a0J&+Y1dNqE>N*3j2hM*8UaAht0cC;)A_^g&cN~#7)fwQB z*RX|oy-GxWq#v9wFB|7%!E$?o4PM>nF?{hF>olz#+Qq06+Lj-9KPa%(5u9(MpNt1m zk|L2x8QkYRLF?)A02tCQsy}?Rp+%mNl@;_SPq(fzohbLno$glp2;{*|jp@3*M%k^2 zBJRLWx}GEa@~vov6hV0){)E4ro|OTF(0=qR|A52@YS&UEWUk(=+-CMwu4+z15*NCY z&2RHg=f$_L^+)gi>(HgX{Ebuty04M3w35@aIj6f*7#aJra;Lpy6$MTn zZ*ZzD#=mSL|8Vv$<-CD5>7M3S=xCDW_N_TzSEKL?$EQP}*Fedh2hpa3RFw zZ*~G#Rbe@645z#v8t2chNIH<-3Zl3YWcG5^lKEWJ`x3b|M89IHO$F+L4St8k$NJ6`!b<{Jf1`ExV{J4DAmFzHX<=LX9~1iC zvp8Etg>jId=Cx}~Wa=@*GvKwaNi<1p(d z9TvhN(0RRl$J~Aeen&@Flo~YwLWQbR(qr&tF*RHoL=puuAqMAnl(7Gu1yIU}537Hg z8*e+o z>X^R;EVxq~1JXfs;4!Wjc5_qG8QiB4a3O`1u<}2upuKQo>^Xg4V<45MDh2|p++7|S z=P){ZB|LJU8Fa)zVh~S$pmxtF{{X%h_S!2YzWXc_1WdcN*=4Ep_sP%kVYMOk8%Lb) z&j0er*(cz@smA@6Wd6&Z>w?Ym&pJWYT`S!4<_NulUmulP?OV}>y`VGfnh%e7QFke@ zcN%m5xghuqYJ__%SAf*7P^yQg?goW?Z+llj7v=CNTpX|Dwowsb13h=52gd1F=v+*=&BbNrMgPFw1^nk7_D z8^d2@qMpAlGwu6^f(UB}mlT zfbjIqn1;SmilA3|9J3q9i>3RkjZgVqiz^Rb;DGf-3kImcDub?Kae;REhiv?{ReNvLJNp*)J)(kwF#NiVU|ci_LY>fwq5v9Hd=FS7aYDSZTD!B;ppTF$kAc}AKY?y5nSYpHOCz}~;Y-~|n z7xe$qJ8NlTN{bG)PUqXZc?ZT_L5+#mn^4t1LI5&k*v5W1bm-EfMhj`DHSttOsR);A7A*R#J5D{A7)J4W; z_;H6G(3CFvH8!TgX%14$49^|ZDy_7BeZoiCGJw!YvT4r+`z}_^e_$UdZGq{%QOTs_ z>lJ9q-TbGMM!7)Klo_B{J{yvJik~d+>n*W8ZP3xhWZmYElMCR;RIdBkpRZ$xSp3*w zL&xJb1g0zT^3{T<={v|8Y58i<@OExQ34_(?WJ}V76hC{kW#T^~s0VI-MZ_Q~of9;>^#l$IeSjOUsm??$!42$DH~6Ufhk*oJhk49zyi# zD%+xR?$O$YdB(CsKn5pz&AdlcW0iT}a z^D`89eJ_|3dAOaCB=ebkLR^R2;qv#kM*$9=Fm$6)QrC}qfhJv`UGYo+?>oRM!|ZAS zWr;Df2AeYdmTd~5loLmhx~3AHiFC{xE#LmbL1gSLO3xz=qCE8!b~lyVKGkmYB2VqFkR6S8mT)C6oG&Vtb*@=)hajq^=RuwioNa5Y5e)X=b7@^#NI@k+AjV+E6*BE z#0CkuckmMV4k1)?u9Lbb`RsLnLz)xS`HNhrfx6+$;k>PB_(Y&C6BrLn-2oH$>w$$v z2L|`d!jT7#+_fKhJ6)ab)ED4Iuw07rBp<08!~#a<=|pO#w}OzYr|(DGV~;UjmINim z5|vK~8&6eeu_5iRT3S6!HJ2&_G2E~G7d8Pt0)Ofjk$7e8R}2yfkeH(0UwvUmz!C&p z{<9roPK7Rm@3X~G|3zn5J?1$hPTF3UYJr>IUS5{(l(o9bQcO{>s@|<$!UW#JI^*P{ z(Hxc0a;*{4ipjefAuf7Yq~9c{tvlT(&%MDpU+;E=TU2zIYP2nEJX^?#G<>Q{InzbD z&bc_n6Kf^p!VdwfWth&Eku0O%}~@?%e+>VX9O&Uf=y3a zM)z{?=4TH6hS+N6zXQZ+dMtzSKr^uBQfxS1*lX!EnIiH6CZvWaTdOS7zudB{LV^3r zYhf(BJC}En0^1P56Qx_?i&;SZYXi_lkUkrdKJn=NXdB5R*Jed`I_X23OZ&u`jm%!T z?|5{Iou-MvP8);_bc`z&<-m32jJ%Lm)Pjz)E<@7!Db|@za0;`P%IWj~U&>Y6? zQ@|p7$VKt{esKU}mLkahIF0=87h24K+voUAkzV>lv{Vsf81yOVUtG`ZrR&zDPheZW z_2lg8KH8khD>3-Jt2n3Db;|1PWmvHGcG`CAXQ4vlxvac=1^{e5e(_+*sl0ugP*F{! z{~z=kwx9W(N<6SLh<$SG9SA@-1A>>qXCBLp`%XWv*NI$JNUB7O>bldOC)s2nW*uQr zdvm*qM(b^@!Dth!#AVi0qLRpfvy!XUs9{kVZo9mq^F8_b!*WegcroiGzeq9xs(X2d*w zO?&Ru)ukRU$TDu9zh*g}4Jj;|>iW}%bI+9gI@y*1t`Ya_s)ZtqMxK(Fb>+0OG0z+L zw8ndY(JTKLBT%cs`8EgEHv*KXLSW2usSFV|l^`pr{2iIa`LyG@Vm2~Q4QfW*Gr|`e z&BagJNAR&mqB^yLT<~=4gJR8`W9eaW9j0qp$Q(Ws$;`2p?8a2$1OUQ&#@DVp+9Y!4 z3i-NqF=J5%8eer2bg%O#V4WkX;X5jOXKLe|I*Q0C-lsKIfkx`2+l~v4H-(3P{{Tf< zFlwQwPePDf$n{eyD;MF~`G}2G$ts%541SY9kISAn%g7`)sXQp#*LQs#D1ay9KXlAQ z>K0oJR{5VOFSM)dAe496bY z0|4lP%`#J_ZjGVAxYzCUlP#HnoYx-Vxg{OdZlceJxGB&478j=UJ6+5G$+f*pD0<^D z-$G!#seySo+P(18hg9FkaUM>3(}J{>nQC5%W0^3N{;l?Yz@E5v2`$Fry6-p|X1&hR zgFk2E3hRsG3(=$a#=(TEWVT8WgxY)6eEeW10Sh!47H$CI7ekkRzi}H2d@qMl_4^?X*s)M!g#QUvdO=eeZj9KU=-zP{6{`%<+@EP5 z+YTsx-ABBCHa<>9fO4SVM$FRiQ}aLUs`^9hA^p9c)NDlvWFBO#d`;HP**b0$Q_~Ci z-?dH*YWbSszz0FaW(Ld_z<-rwxR(85KzsKFD zx;Wsk(oUd3D6iXaiFs!jB~Y*B01Z+Ouv`MG5i&3@C!A*PW;A+T0^4xf zI*i-~IA#!#{$j1&shiDG7FH zxO(zz;5nUqf*3GqV1MElbmIqd^fwTwBvmryaB!R<5@ZUOpNAaZerqchys8p{kxk*W z&Fx`k@jzb7s6E*nwlwMpL{ryQas+5&M5`joP7TiDw7&wh4Qqv5Bi1`n54 zF1tys6<^&cusx6zlK5W(b|?!BU0L0fAcT}xIe6li?30}T&U}~@M7)^Ha8uqKO8Z)^ z7da;#@#=peOJEKM7{|{Ft)I%43a2_WByxs8om@$@`H#ewH5onvI~(=>N~}KpHLcQx zVT{Hk{YL|^{ELu4F_r@=gpBebRrij(&6%1qi@Ew5;#ZE@%lg%J-*eRq5{5|}qnu;u z1&mbPx$~_PpyIioKYzA5fq9-ef%|ZyLS7B#!M2)Yk#2HW2_)t)4;!vCGkKW}NdLEW z&IR-3RzJxcee{t6I}4;e)k_^Wl@#ASml~%?|V6o@=*UqvySjPZK{UWuXm72*&zUe0C2S> zh;{?WgIb-qr0@+Y-#{mnC|EEUg%l335a!bg%KFR=JHIyrD867(cI|3y1>>>HKP|Q+ z2B*OX4gg1S?iv;8UY^-0+da!1MB#lL6HIubh< zsI`W+USpZ^Br?*{pxN@#14gU|Fsi`kA-HQlUbo|0CMZmC;)h^5XeT>+{c3vMgZ%ie zU-%=f0e2-5!`9owR&zZxfv7$}fIo4@`~|z5<}oCY*{XjEY;8jQ4#CBN5349(Elg{1 zG5+!K+_0H$#ehG&&m_VW*a&eDWRZt%|A-1<5L??!?sf%x!{dVJxU8!J2nnA?2T7sV zve3mqVp46R;`Hv=2r z>(XFYE3K(%X8bn8f1Guj!x=&AuPn!39%k^dlm8!-y)2nCBoo(Lf@)R+da?vFx^Uf@ zW55DFrey(DJL?;u%=amA4xs+7u%+``2aO{fHZwe|T)(Sqvp^gg0S&qt=(q4kpcPdS zP=*mpFg+IdB4Cdyukm33prqe4NnR)gdFjo#|pfj76Sb-l7T^;jr=!at}F( zXx4GBeCSiJW2LUhf`t?mh8SiIFm#RhSoW1(%c6!%z^9v;lJPpE46sLU>{=VUFHL9YmGyR{bV5t5W+93Ud!gUjji|fVHie8RU17{9)+WjMGKCO#*^)%$q zBSd8M)F#j`bUY}E72fC@VKM1CR;Zf@n33LC=#bLkXXEa~u-F6+hzKC-o^WrHxy-zF znRSZIe-C}-6qvwenINjh6$937Cb&OIT(;9Mi=H;#`hrTHxlo@eEG|w8^d@zya|sCO zhVBgWAl^Cg`fcVw>rN0!>})@fB7O*ZT}Ua_afou=;a>`JR2?!U-O0CHaiHEs%UcEQ z&4M6P59o+)gLFem*AOWNdRNPLI;=;l?TuvOOA^z$Pl{WX`O-jx(Ot<7pg|94 zw9nw(16>7jz&&G@(4Gfc*2@83ZiqNuW~L}}UsT}<5wN=-n``A6gDfRM)}EET+oSQ4 z?!)pI3>sT5dgXNg`s#e$1WJ;WyBq!lX=dT$I9a%;ya1nyds$%q)QVK^%EPUMOtsH* zsMII>3C~a(Y9wK~Xq?}T(E$+krl&?58}yWvuNy8l^Bim@3U!rFfun=%=uYb$Cb7xS zqUpB`e0d3+(p99Eh`Gnls32vqB=`~2pkWWf!iym>B7+Jm7XWQ;hhsOEkjedth>0caKOS@_l8zC_I~IXD%sX}-prdDD z*c*@Dt316dJ;@||k1?WxoJB2`(meQGbOQv7uXX$vy6_mn6sxF!fcIxI(QKECOmR6z z*Bm*f!EG?g(wQ8h_DKMd|0l>AMnRS{Ww5R{U{wga$*HnCMlrq*zCJ$s2!*T(Gq{8b zP1gbFu-gC-1kD0{S{JDSPpd1ZFvlGb_hEzw2zG!|mMaOwR1WXezRE9B!O!6b8UxK& zvSBR|rgw8Q`;A1i2z99n;2Hr-fsi}vDJTa%fAPr+d4~6{bqe$a7B~C8xtj@~2EdYz zW4F2y15aB6p0K{#+Q%|5fC-6z6nzl}r_4X&xv)84;r;xm?`kPv2L!#1eLU;N95{DH z6a@#2|8K=nzRzuoKEj<`2($Nno$eD#STgW1wxIYh-Ul&FKf_Xvo_89-Yd2ClE(_t5ZvM)K!b z1@;4;&<^0dN=tFxIpnt{2W@j-VFDp&x)#4}W=IS2uXEES|yBwb7x6q^zC=?H;hour?VO^>u= zkgQbok#JhjaIbn=eTF<$Oapz9@y^?muT`=XGJsG&BEY!!9fW0KEs={2&9p9|R6bzY zuX(>v_Z3tNkI>UjJY9amonxl|Q%9r?MFH{$%Dtmyw6=-dyMZx4B}&d0 zHoWq!&gqp`%~7V6UMtz_VQxyNmJEd@25hJ^Wa)84Y6Y51C^Y=}^%fs*cNFmafY*R% z^+5%+H+(ffBe4!dBMsIF04nRMWubqr0**H@TBx}0TI&qkt^j9r95u4b~Y@G&3 zWAu__P&%HbgTu^7vzs^MD6R5!g<~Hdprv0x1w3+}=()ZIOs~48v583z$mhEF&)*1N zACD+nfSOpQ&H(0qq`3uEvKoNj%dVhFHR2myzCB-IQWcPVEx;`yJt0002|S(xxGD;Y zpV!+HKXo_-nqIjDB30cbazGyf727d}Pc9J9+fMpE9Y1-x&ir*9wCLM*RfPRhYpR** zF2vrz*|s~iq=YweA-uuT5^h#P`bae3YPEW`HBm4ygnU!D0zgHwzQ!`pOvmA* z024$~wN=f|GzD&v$6>-+ypWki)6GSmBBrn1iIyfEP+h;4Q_@+d<^a^L3f^AhzTk_J z{moOF;I}YE1F%t^P@4pNi`5Y z(K4aL1pUzH2>dF`C3SE9h}0|7G_%n@C>o{n6_CM$dD$*|1yW1MP2Qd@-v7 zDa?i3dUZ=JVXZKeqnhPQ%%in`wZ8O(%X2^iC@q#8w-=)5O&A+x@5QxYbO$Y15uT%b zosysWA&v%d07rbz%Nq}SU5(S$SjGg0ESJdUqj^;~tea|gW+&h?EHjh#KujN)o$~J%|GDo-b&}bU=pBF7ShsLeBvYmOqanv5 z2fSVYST3Fsak%aDYj!M7MLCZtNl5seFNV-{;YEm(V>Ol#20QhER^zAyPD@j+@PRVl z3-I2PWz$c15gl|r+nxZiIqomK9=1X0PUJ4qYS(Uis$pvq{QiIJ4eNta*4MoP>z98@ zTOhyvug1+kp#9o)wZA*>$=CnccxJ`UJ?Rg89c%7JFt2aT_`c=LuD9#p{%BBV+Oz&4 z(6?t6UQzD1ak}+&*5f^eP3bdgCZF|}X;F4LyX%A7T;NG0!DWu07>*ks1&&&uOw#-R z`}-%+(?^dUKQ{T{$B?@PTa66LZmMB4ABFhb`X-*7U3tUcV=JgP7p#A8>#pkWd7$=T z_5W|j)fNC}0|I~p_)qh?B|qwgndyn^|GXFYtY7Z6m* zeSuoweDS7^^YILP|DJfOotDnmNHYHeobr6Juw8D`l9=94XGL~@tPDH*Hbwkn3#YKh z`bzfL`=Kj4fE^!~t^*J6^L0Nj*njWqDgAk#pKctT%>j&Ez5cb5yOTjZnVB*@6`3t7 z?_E@OUn+B(tIlO9aDm7X^UH6(a(RE)W-x1Zan#NQT_4%x_G)`&DlafmxOrv~d;QYb z3Z-`Q1|BIBkC&1wfxDotu8j^i+bc2k1KV^qUa1pm0{3i|q>E2FBJEW%Inbc7)I6?H zhlO4FcKp4BowmSY%1c^*Y5Ar!;kD&L+PQPi6wg^F9~^kgb>Wx1q^rQ`dC=NOQ{ZV; zIkW56NH^}-pucX;vA+kUd$-)4!(ZHT#df8awBbwRzh|aAs(X2V|NcvQV#e$BfA0GQ znr!sCZ=#vI!dLQIuR~4H`lqM99{l;m?^TX;8E}t2*JokFb=?1YzHEKyZmQA@+!DcJ zJWo=(am{_hzRx@ISpJ^bSF`===I34J)mi+rFUgrI-;~+DQ>MS$=Gxb{x5LdQ%$oVf zWzARiPqN4VXJ#es(aT^dOa63hkq7I#=@iyRismQfTJuxL{-@d57cc}q`Y=sAIf>Sjjm9&2Cni(C^;JV{dMx3-@ z-m2tPkN-CS8!|dC_cts5-Jaif@pNa`i~ScD0|yl^1J@z>+f19H6FTWj{5!$_g4HHX z(#JPD?0c*jd)dUQt=CWGf86O6*Wb>6@a&sh%Rf+|%*rLUVEMeNt}p)u-F+8E$eurx wWU~00_X^+;254mJ%lxC4fw{^-iHGH%eX>&R422W!YZ!pQ)78&qol`;+034dmIRF3v diff --git a/docs/interfaces/lite/pics/existProof.png b/docs/interfaces/lite/pics/existProof.png deleted file mode 100755 index ee5de0851bf1d1a0ea503fb03b8c745547c58b87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 96053 zcmY&r)qkzHu1n5mu>t-OIN_O}E&WQ!x$idqy!XDczw)ka(ztv&D2(<8iuALj!2f=@ ze}SN;BG3Gt(kAl1U;WP?5P$E>OM{F1Mfx3H0^!XWE%m?8{?8IjRQvzmigACH(f=4;6;BNzko|v4WE6wy7Ed(F*krJ1 zc2!M>sbxT;ShQ^1(`#3U6q!=_LZyniZj&3<{|x?dZ)D9<@++6B$om<2bs?SH zFjNW^AtpqSruG1-%UGHcqc}xSm9kQGE5XU6-bhw%Gx|I`XJZFtVRTOkmiG4*Q7jB3 zDDb;MwCgyyv1QGg|7oew1MT*GZ1n4TfLba+t$Q+?cGZ$K>rf>xrn!oxvlbFEGA`>; zWvBWM@kgu#bm3S*APf`d-Xv2oIi`6ab8}{_v_mqyn;Gw#t(;xHSt-$6=zU-&!Q;17f7m-}W`K^L03~&~?Ye8%|fzpyEnzh67@>a#Hq1lyR7FGEgcFLwxko-AoSnAdAfw=_!Kcj!w@Jb@o~RgjmHT{ z6Du$-!hjPLx5QZbP%)HeQ<-u-&v>ZSsfr^D>wt1K!)TPlOaj3CvV0UA1u zw@xE)K|DhfbPi>QNxysiA;u?(W-bavT{5cEk<=9?y>DL@n%g=c3ecH$m`}=5)mEgc z^p(A?%I!8)S2lDcEoc2@1+6<|47bXCZzizc(8P(Cmt~zIOrcE%&x!*fPemRUv?kC@(2OYXaK!_k#4tBu zmh68H>%s>rLrUfgak92ff2?%a%EVx@WGkP_A*Na_MwQUYU;YNjJ$Q1VpGt zXk^o*2NfCsH|E%be=1PJ^Z)RGu_VhEs@H9E&S;;JS7+$vV)fx0LQ4CeGIAwLS7W;+ z1tph=WEM}TEibBRBX^vO!AS%9utN$Q{02o(y+N1&L5K z^d`isUhRWL8B^itAs-tPKzq=Ja6tnCte&Ua#qpc$kF!vt2D|NRB`d+8+EwVBA``LC{Cfla*VgE705&pd zmyHt6LEEtpqy#IxwSvLW8`giTMoR63FIs+xd9Q9Y-`J+HPT2dN&~GIKJ>QPSZrZ*3 zl~+p(+r;nVEI-5j(~?n3p*`VsQnuex}G_sj9M5 z=nfeK222GLCF{vWHfY!6{vA1(l5~%0oFlnd?Qt6S>~d zfO;?Af;R9*!+Ar*8Ard#r?OY*uqQ@+%6zZFzrZ zg}<*blYrdwg|z?XI69)@F-($4KagSf^dCOkz^bvrK4Tx7#KZ65kIHr=Ch*WwvE=fH z{s;vJ4{bdsv8hxt6npa6<8(3ZQQ0&mRi+T`y+tt2Od5>SrQa23n5dv6wsO76s291( zLD{-NpNc&?)5~i>4`Z1Qb#(;%S{$G4(vxBLk*lm9xtMPW9tzjr0+IDB=}(@2mt)J) z`dY!CzNS-pIY;bf+K^Zek_v@a)LeIj2O*fEZkoI#a@46N+Iye+T><5{a9GX>eA)Z} zM`hA&oy5@&EZCC_TyQ5?)Wb9wC^At2$hlovDy~(UV=5{thV@B~TO*h{b*}q`5d#}J z`>EHb90y3>Zn;ER3p3WcLSSn&p7wNd+AK+wQqNvcpDFG$TE(xnA@-sVgt8i~=tSIR zPGhW-NhiNSP1k(UY&YYFL_B99z0irk0RBE+?S|`+cosK}^zkQD6pZrM;!_5PFNMQj zD@+nKVa4r?Ff8T@#GO;RMW&f596Gd(m*mjYMDSkajAlE>b7!qFmTm|;s!0_Xqc>dE zrMR=k+b5oRns=Vo_zfFRW_U5ZEXr%J4%^J2xjB;#-W7`>Lpt^RE0BWC_ixBEy1g^f z&%L<$P#2#;*y9)$gFC|~QO{V{b2Ra-3Ppnwk<%mLO2OO%tUbB@QIvs819)-0 zLj3`S-CY6OGP{}{GQ2qv_&ih08q<3|7|xD?tY6o|iD`-MD-2(ZOpYc%e5TaZr+Faj zFeBP$Quu#K0_DBNYJyZ&$a?v*S+LvBBJ(YA!;O7;p}1?tec@vwi0P4hyI(14gdV3- zYcFc}OmFr13Rs;<5y)NlM;m5WszsUo=Ioib8frMZ?%EBncJ|~K(l@2>UP+WxPeHtc zNl~p6j1G4~T&);Yj<0Npn~>iYe}tAg=sRSyrjel=E_51U_ZM~Dz&F(H)=p4HW(-Xf z)@_znx@N&2j%1mON82t&8FeO)5-uf{dd;I}9*>k>lW%VSd$Dm5VIJRW!c$Svbhj{8 zKjhV1myc`fm_>ak1vz`h2)-%FG_=5f=cWbo6+beCTo4A?Q{d)p19~HfGY_4B{?#hT5l%X zs^QH6avFESAi{OhB#Y9(n#s9S*HXeFuPW`cH-iB$>=eDi#BEcqMowXsxiOp>GGPz? zQVbPI%Vu7wM_6a^1XJl)f3o%=ersGFtxF@)O?>dRtk0zJa|*_1D)Q8S_JjQ&oQwpm zNKq!d#`~FJMLCWQEBe$wGsLMp^*ImZ{oLo9rg;skmPw!Ec1~X;&CKEUNSK@S5)QrX zso>3@fucqT$kJtuAxdPi*+lb%;&yad57r7DYG}Ki7O*|j>f6gzr*cNxqp)ie{5eFH zcq;RAFK0f?=2-NqSoURN4oWP_dZHPK0;<_i^{k(&a$5A#sk`6k)3Z$UX-K`$6Au02 z+GE+Ug*_W}7R#r@-;_vjPvCJpdkFOp5YayO2lui!eiTBDsI7a_*5+WHNrm2peM@6d zoSh#+NrtVH2}qX+X541NSz=67iNfjxO=T)F$v^T~qJx*7rM@uXP~6ER))}oSFm$|l zLlO(?8>=*aRVhG|JJaf!9fn);IK}*pBwFTo-nr<=m%LDY?XjJ3Db+om;B&0$RQ>00 zh63&AFc4VEeMT=v#zl>0FK4US|Mnu`TjLBc*4gUxd#6E;557F>d`DQ-aeO$5h-z{p zoS3}J(BZkmyq_gVW}%Ht$7A1Ka-j8rq_ftk|Gjlr`?wp=X1!X2R9J+Hc!(<@Y04KZ zXk&rCCAidV^Fme;+Nkw6W9X<@MM0};NqGLknTgp&A!KeB=gFE+{;Hxp^cM!O+`P&} z9V{9)VB!B!l3$09Jeogiwur+pci7d%!Rs#fm{x4u9g?h+AZE4dQx#U4u(%JC0#=ZU ztWA|F2deKa`Em!M^P@7+@8wR7kHfrfGH<>FaKYqMr%E>CPV@)tPvWLc;pra!v-x{Uc=vJ!uZR=SC4-&)21huveo&xsL8jU?U}y=EaSbbZ6Hq{Iv`5_LdwUPuxVR z-6;7=xd+9DN=&9i*%GcFLN$f!VPHlR$B`9x-4%~y)+|^p)y&F&hW`+79mL?9D>FgA zRm+S0Z7r8BpfzybMn8Quy3e}XP(4?5nNj=X0MV0mT_v_!Q${7F?BK@JBy85QLI@5& zz3U+=n{#+#n5ML9QREiq2Uq*&fbmVd7-?>-nfd$qV}kgUCM;#l1XDbi0KsOndgwoW zmg1!|Myv-N(Uw{=@#-qRHW?MFxk^@3VNY8PmNeORnVG<^6XM4Vj9dB1H_?cK>xi-= z@2+zZuT`xRE4y2(h`wA#p9tycgh@x_8%ZyC;3SwHc_>HBKJKT}_YV{z-_;ME$StN#ilC5FIK+{xv`tSbw|HE?d))|n#_voVcxm50N(qLc1Ddo$R!^FiVQ8 z>-~3`;YO8u^FR7*DGpY~OAc{nlHhk4p_nu`oThIOnBz;@PmT^Of+Imrkjnp8QSny$ z;HPZ4U;7KJj%%~1&lhpQF<8VE)4WpzpQoj8mSV55g)6n&Gn$N$p}Z+J=*}>VRXKXRF zxh+sC6$Trdg4Go-KRffRcsr!46IoCnruj+GiGFJwM&a7%xA~-> z`Y6u0-1(x=7)h$xOidfRn^)>1xt@Bf?(e0*20 zHaKlJci*Ow33CVAA%PUG6t7bF;^XB0!@=X6e^9qWlsqV+Sz_=(Ts8o{2HK7#*RPce ziipSf!41eTN9&SVS~7aHTR};M==8liQSX>QIe4$fS8-VL^+xXTgrIn?5Jm@c+Qw}Z zp^zz=Ln2|pZil%6lgaV`8ZUL9Zb%mja#`E~P&TikiLTlHCPIAj$pX`~-wlVS>lbnT zbyxO{z(m8E&j!QV_0%7mFWF2?|JXdy_mAK+`9i***UkhEJZxoM8m)|mK>^3FW?SJ- zc{BWDx$epqLra!b#Gv+TE$7L^CbR?s$^02y^-OLet`7+g<=cN~Mj1L{cY4}k8zsI( z8lYM>*gZf97Y;!sW>C=6{K}-oA6WIV3S~gtolUOpEr0t1YfGZRWyDCI0^v&g{>%9O zZ4?))C*4T9S?k+y&ivljog52hpi=k{ISWP&@mM7Il8ssaHFo;Arpc)0_)IvBiJ5P{ zn3(h(qwiA_$$YHAWi(z7_xygMKa(;7pAIBi9FUR-Yu#;1OYkA$L%qJ7CD?*4+%L*!~H6~SVA)p;08ib?a`g7kcn z3m$w=xdwFaw7~cDEkj^Cbm$@KWq%j}O5D77TAa!54S~ZneS2aAW!mI`gDcp}kVV@8 z#ZuZhi)G)9)@(Ohg=e)+1SM_wq`KX~+58t`5^moP-&@lj*0t{~vaXKJiQXjz8n0Nj zy&;~f&x=_FCN2|)7mL{&L~Iiwv~O<^`Sdr`2FK$_j4_9sa_RNk2Zrq{Jw)Q;kG$>8lehUTF0p>Y&< z8nwM&&ftjvIj!w?KVAIWYsW*Sdo!17oPjgu10j{4|$wMvs~+JNZPPKx56Rsn*8mi319O9Et;o>s@1tpENh zYl624Lv1&2`LRvQU@cdbkLm(OhS;H&XemuS82BNNz=oKvc}?~CkjXGgOT)*KmzrCG{CLz6j0Vy6C%wk*ow2IbKAYx2+S!_da7MBEdyp zus35)2{9%n!=@6l>(c@Dl_fbzz_u|7xG>H*0M-91qa>3%eR*R~w}c{NPE@Wo1D4fq zE+~Zykecn8$~^0)^*_~%r;1Xe>*ak4^Duz7WR#V5B%r>ip^-{3I=rA6C?fh-)>HEM|-TyhW-Ulmuf== zYtc6IkK{iFrwoG=6hqP@bM7NS=h(JtIzJNB2P!2ECz3YnbG#ghX*!xroyU&;E1Un+#hbQQ zql0Ekwn;D>^vNwCE`dIp;&~pUARhxLYk*;lmqPNPW44Qi*ub8}-`ejND}8yhD*d^U zw1{hO?yX#g^kWpft#AzQKb`l4rkM#9Eg{Z-Dg0h>Nn5N**>1L_)w+R*-t~yra(Q_6 zGODB{=dQ$;*XNJaqT!4oic8iGTsjalH~(4@%}>kIiC#dJbUM zKwV5G58GwS=p=Zi#ekX2R~oB|C7c!R;F1?sl}$(xcL7S6xSB%_Wuz#Bd_VC%mVU)+ zxReXDS&Ux6*hRApAq$8;TWkyE1hAP6pF1a$zY2t}Etn?m1@^D_Q}yM&Nd1Azhz8#d z`2kryGH@o+#r$=`25O9it+%A{Qf0jC%vS3xw}s=CMAN2mewEhz%$AUt)=KfIZp*QdxNCIbbW zikT>8j~~{*`4dz|C#Y9Wt=l27l2h)TYTLv9iM0!of~hQkon4+_@8#7wyjF?Rr!}68 z{~4YhWs8%lcZVjoxnq-LJOSpiU)!mAjej_NtnnMS4@Odh_i&IkMT-mkfX)jD!i5n5 zt4*dg%Z_^HpDVtvf{btbsE_1Kh+AT0e~M>Rr+1D2IE$WrK_NhDU5M7iR#mEuEkH{U@8JyS{;`?p$#XX9A{>Vv-g~Ce7u`*nLR|*$*Kp zYtCq_{Na5n!n6Jc1rFyRx|V4QD&^x@ma{0E%Jq@GfAM>KVbtxH1@ylC!o-_kd7Pbh z@U<601tRQ6?XHch;!ijl4NY6b>#Poi^ID8%uqVKZv;WBpH|>A;{OyODwWT;jzzfsd zkLT9l!JS1_KR`tpI=`>cmy$XJT75r|AVWu2Rzo!YYE|0mK9Pcjqv_J}yMW&WBHzOd zZVST$(sqmIA8!)|KTW4Z0~Y-prz!+;AP)Qar#9X+y!zgpNEx=HeR;k%oDXq`gOXw0 z0+uqYl>TC(=^Wb zUhC!6$aaxbsM&3W6O^c!VuC}I6*PU@GO^fy`2+L*|G!up7)_2N(pPudUo@g z-OQFiZ&2I`wRZb*UsweLA2|cY1Z1okmSDWV)hbI_YfT2toezxT-h64h|DDSrx;X|D z)#%@d8s#QW64cD1iaLZ#K^r=X%R9O_!rfdp+^OTJI-7Z98%bnNRpdGgyx#%Efy?Zb z*Ocp#NsX|`Fp!&@HV!U~vCj9%Lnuy)cq^gdhXPfVcquKWQZ%tcKX!tUjPF2a2Xy&q zi+5y&C5G-kYXZZ{=dp?ULHTvRs1q`Z!@YIu_~XibM}hmITi;abgWG4Z{&Y`K;d6w$R^aVgsWX%;Ljo*_?#^dU zhvY^U9@R)}4Jm&wB zIozL_2`*u8-v+T*Kyh2>HXi?O?7o1h%u&R(n-n!uu|{O ze+E7?KRxLRmo_wf`vRc$C}jLihZFIQ^(R|EOGA0e<%b=Wu%bOkRqaYxgZ67?EOn;O{F91&0?uf{zLGB3XXj zDd%s4cJ8gbXJ00YoDBBuJ77*!o|gjj^Va#sSrHlkF{+%+6WGHf8tmvll3(Awpra8c zpD7F=B?e2-GXV-I!C8iaC)Tuf+%h(`t5E3}ZR*NBz{Lq|_}uvQ$2M`2 zEI2g&=l^loazN544gW?-1NQsHu!60Pe%BfXwqD9of-tw6QRKnIFG|P|w$px_3!MU& zA6J(|@96`C!WvK0KbhsvztgV<4H?Ex90N8zLSB43W@ZQt_H=W?^Jkk9ud ze-*m2>5e7ULr_oS#8zy0Bi21s!zCZ9A03x%BduYc)4OwJJpkX;P6`YIryDaJE4DY$XJ>yoYv z{kGXCWQMzehM=ddxygoZfY9m?N3rX&R4uXX6<3jvP0m)g>&=-WaXeG%DK-j!oU!Vm zKDh`Ob6q$w!SZ}Ne~69#(4Jr(2;ynF(ycgnVxlSl?H-?3AF$h@7t8Lx>ifz3t#i|0 zWKByAQLnzONffo~5PCcRhKjj_8=W@h2r{DgDrZNt0PaJTYeu+kjsd^4i z5j}5{u)5{O>}O1da|B}l)b}7`^ifu{Gi098)@7AO8 z5Jye&wx%4d78j=1mc!fj%*?3oHWG|0;+r1Ry$zFQ_dXs_^XhpXo+60<{R+~%plz%) zcggX35Zk)B$n;Vhp^B7fYkRgZ`E5@=6se~6a0W#}Npy;#3Z!c`4G({r%XrD7t{m0& zlAFnFqCt^{SIyVB!m_x-2dohsi~kj>V2YjSxU0v-PQ;T{LJFUL%B1B5ua)pvoD&Zi z8ZfOlte`Gr<&RidVWm#9F&}kpt6OXGgf*~t6hGd$D6c867cE*@ujngtERfobSo$W{ zdO>Np9D=&F9bJK=dR=0Zx$6NIzLOUp&WsjyMCkjG(;Sh9fP3X8Z5lV>d<|@wMlI$& zC>HSuP2h5yCruatKfQZ3lsUi2Z-G2x6wu_yjtUeL*Sykf$eb`Zi*TZ9uS;s86&Jg| zH#o20Xo&_%!ZIL;qnrrg{fJv6F>0>%A{by!*Q~pN7L|G1znU5KY&T_k>>ODk^X{Mu zBJ1>vvVUebyb5acaB;?Ple00M%|Ild@JfagMo#Tm_~jLId4s4}Yxhjw<|S(~{Fjo9 zY0$KI=WK}Xq`ktVYq@fYsux<81nUrNq;B%7Tt%0s{u;8*&#L+*o|Nz4Kobh2UAkL3PWcd8=GwiMoZMxK9wd zUX264lH<9tL%Cfd&}uOm-YK6@&ZK{3$CEtEZO@f6v@d%CU5^0{*paFG%{C@IZI$UC4?4V*|iWW}!aLi^0#*ZSl z^ewwPAM)+)Vv2~=89ZEUA`~}rQAlb*(&+U5m^*{a``b~71W)I)gk4>VOQZAi>WK}g( zwebJB%9!GD<;${_P|Ft8arNm*fK`v$7ikhqF>y%C=lMGkwbU=L0iOf(H1Ji4T+2*> zjumni+S}tCUq%Q({vD1&ALOvs}t}fp7bcxCJL?alPAY3~X z8JQe+ZSO>=rE8hDye0Alh zq^yj|M>0bbNe#m{0P5=H(_8K4?8<+}I5tn6J+G1IKI= zp#nq8%F0N2dDGD;6LY-oPKreUqNGgUzkf=XyHAhpO(nB zMd}RK0TZsM?nMEecs{7C@9(fO*qSB%o|rr`Jly2>-T?rh5b_kASYRy90i-BJjKQgr zKxrTgsA+*WEask2DSMgK-H!}73hB%g!IP4bl8}*6L30T#YV&z!v#i&WoJJku0$7Nj zj5s?wD*4i*fZqVD5QRRvpTmbXw9Dy3zx8Re(o?JZ5A>&-S5Mj%x_6*w;9Tb3b>C&0 z!@TdNOuYx>j2zD?oo6A&ZOIv~nN*PpA3RzVmZxjfoS>6XPB&b`Xwb=Hx|bhxV1R!A3Q%(&_C(%=#S}!-0 z#~rX(FEHlh<~q2!B|TGHvH!cG1;5_c(xyAyG-tbfmV;s0d_xL{m7-5yI}D8V&^pb$}qu>v3{6BGM< zMcLUK#iBliBRW>cD3Kn*RpVh}7aGTVd3n*GD#t>vm20!_o*SMQ{NEW(;*Zue`u6;F zWoAa!^{+Dy3|^sKqLE08T>EnGBG3&vUx~trk8q9`i>r)2^?CZwnQH3-+Kk`Ice<|U zOX3xaV*RhA_{+COXGMhg8trj1^KeVe8kAMIIIM5bFEn-+mznD%ec3cX@+hOxiw>x! zd3^YK?UE*6Z~i1l7sMl+?&|hdDs``H7Hq}MjiCccWq2oA)BWLhV;^s<_F(y+3XR{# z2{{AlJ)wZDtu;O)$SX!>%yv4oVz5-?y8{Yn=0i{=_Y~A(+t2qjTeK7uAr}|+q9W0_ zKcvDQemIlYkJ&1_y7Hg8;-U)D(bKB|iUwkc)DyS*;@Wa^b8BAcm)069iz?8|j1xx4 zE)sbnOxD5Ijbf6+klB{*z2=2hdEGNrPL8VV@q`i*t24~)NwA|$r9TY^IAx~)^ZM>s z=3#2$!pj+i(&;%kz1}Xg*6{;h!qsd|+K1zISBlv?`0@zE*x~*zES1||W3GfqF<(wT zYXxT~7i~BZelK~A+p~2DdFjZKQywJUG^W#aSZ>AfH2HTYHrD!O$LS@cV>FM@_C&7{ ze!oIFnWX@IsF3|~H#Vg0Vi>>$i`VSv%u7_p^{Y=XLS4mgO@}LU+(0kNR_0B3Mp%qI z^R0)ZG9IcVs=rdFIfryMjmstc_iua8K9 z?J0F0zF}>9qVp}j>hRjWwLU6JT^8|h9W{X}l^eb}((iO%1S@?b0NmGqYJJ=}dyFif z$9F&M^VL~x#g=Y$Xj@nZCJ>eNnZ4kfBEfA<*4!@uv4`HhoZ!UO{X|O6q4ZLxh$wVV z*%;I!hDcD5WN@aUSC8FhZ0^v4>z#g{dJ)B)vxGM4U%~2U`v}Y7HLtxbhZERh5Kc1oJ;K4dHXce^sPN1AvPB!DHo z)%~DzBP~KB%FoNoo4M>e;prx`_5rUMR3Cn@;lvK?GST&sT@spk$AI5^rb*zqhJ?bA zZv!tQquJF@om*<_19&TJ;lo4{l1z3z~G{J#2jCb7~RL?$rz8|+)bjAB0pBSNs+lf8Y6HE7k0FBI4 zFy;_>UMe|-C7dHzasLz4CqMjyzY)>rBM^Q@s!o(i&0EG%1I}g z;lP|+hOapx#*NSLvJwmZr{`a>c8K;B0SKUks(%`N4ln60Oo33kgp zICEellrh+|LfBMfj<(^RWcnACH?rTPebgW7OHef0HsB9bpYjZ3%JQRqtFHo}@d0t% zDu5bA1wPsgXX{Nd`h|od?p95{claj3U!R;~gsiAHRt{%YMk;cQ?g=@P3LMCY!=!34 z1H`|#KO^Ntb(XHMJhqwDduNbNegadnywLuzUX1EAIyCFRsivW8Q35N~+3 zc$MI0#|Kry3kb5uAm0`ug%_kMnSsl7*hHm*Qc{-YK^<9TJ26+7e==##7Tc9{x_fwV zH?hmF!a|E(q9_mQG=EH&Dkie|?SZ zwo;7$R>p=aFDa?mh8aW_Jvff#1u3cuD%h)~^d@J(;@hx2Bzf{^pqL)&RD{_X^2rA) zAhpE5qAmnr5J+qfnkX2A!e*1qi8of>UZ9-Z5hnA;63GG&P+;|TPPGF1jB`=^tp!L> zi`Z~0E7VBtM8l~WyUp7?-!m^XFt!Sd&)(4$hxjSZjBUht-oJ4MEeb+fmCe4=I;fkq zAw(Pc6^EXMkGdJ;lGb#9|0nUJD3v7YCMK#3&R6$D62LhfJP#3steDK(sa~(yx(_#7 z1axbSdaY}s;6#V)#5+7##`*1Cg+)mVgbuE(=!l+#j-Grd8ou!EKiae=5pXGt1a`>D zLx%eI!66h6ud7I-U-19(i+21<4N%^Oc-uRiHPi(kWqaWV_5~tTfImcN`rd;Ez30@V zWFbPW14$=;!?VIOS=6dHoKNErYOfy7ma>f37iH?MGgX6zn|+=bMJosnSKE=E&KE~W z*6KQM_pED`lyoE%Eug8Ru-M(?(;~V0;)QQ=89P6v29TWDR+y*yizOJ=bg)S3t?R(S zIgkL10qD(3<~p=?5oFfH0MXtu*;F>E23M!>L|u9r!_5Q~^L_lker`GvMY-}o+_ooUz*Y?i>@e=F)_UO(6Demt3w9nfN3dYl$XNSU>f+PoD_X5OBwiSi&N7SrE)=fDg_9p(WHy@Tt zg6A;?DHPeZlfM?}xnjDq?T@D`17f${0eH<$`{UrsO>8XkTfzxFcJ?o!+Ro+Pt-Obh z=HF-C#K~peqh^Y&f2J2DU}e zcEI+f)5k#Hw2rC}_$NQms%mYJLhx6P1&k~K-Vs=K?65V{gvyr8xpUlTbL439xxqPY z19|+TeK|kS@NvVFQb}%OE!j$wS8j}@>M|ahiwDOUgpG=GikdL6-x(oz5%Y8wM<_B+ ziA}rF#BOb3LP~xi(IhDn^8B&Lh1onT>-ovJwUO1Ya|2pUowMJ$azW&Se3;^IlLLAA zXgzor#DLpaA+_Ga*JKKGI)S=T3$=}I=XxTq)()Yx+m^WwvBoni|aYw6%TjRbaf`qdI; z_HWT<(!le`LqvTiA6wyWjHyIk?OW^#bz2^fJX(%|9dNZLUr%NVAn~x@q;9m;+wja_ zIe&REtD7&VwU{TC8WlU)g+B1%W^p=mhe&gg9~)LulzG{kXfBU1abFfn^udu|1|geE zD-9AyYS#Au@p6DXr(YKDt!kFRW%>0<6*sedNjkIm`e1PmJADdX-i;lfG1lIaAC|sw zdtYZXUB)i4tyTs6!&pKBk8IKlXQ-0e@R{l9cwSFKPHmM^)ZdB^MBx&77vUIy{CtrP z88!rcUcM0qyUNW|wrvj*Z|i_0HSd*C3xTWSLAhLLwB3w$-%eDjOsR4?G7bf*RPdV1e5Xp4bgV8&-OeFh*Q#fD+h#ITSWv zU7KbO6-66=tr0(&=nz6_WV^XEFN{~WmJ4x*FDfef&daO2I72P6yE~FpTvn!nmMfwZ zfANIDCTu7pDhT)C`v}YsgMIz!;hsPi>(#pS5H^&hd;HOO!E~@~oDLwzrUOZcb~CZz zw+&P!I~`*04pyMN1=M3pA1>42M&*M-G*u(@FOY?~AJ{@cX$u{p6YPamJ8qTeV$A1n zS0pcm?PH?{fHglilGntSj97y7W+zjc_u3O47QY*;)t6Cg&GtBM_8xvik2ckc+Z8Tfm!;L9g)DrjB7FXx7*hlI`Dr z&DrnRd~43Pcdiu%YdrZ^5-_|(in}A*poyFBb@>n&J5jK$FNVV*JB*eJ+ z?x%`4B(|+-mXpFI<0fg6GJ(fqIT4eu{ixHBOyxu#cs_;iW~V+%G|SUNMTAHcL;8gx zvR^d)#4`7?Lbr7ocPi?K0MdnyqOLgUK96Rs1Z{}AHbNM7&|13}`q!`D%Y$%#HMRwj zDiA?T=*y%?HMyVBqBw>#?UKgo?DeG`ZVz#`rYbkf-NY!?y3P`IKSk$Rwc6)!JNIfh zr;fpnZ|q@5B>{_)PGu*EeJ-3F+>bi6ha)&@?$B)yyja*uKn!kqEbrI|@C}7mmz}f& zW?M?814kO~Q)b5Qu4YG|&wEOJDVBh?rn*n*0Bo>^g@wfe zYM^BaF1Hla)PlhzXx2rfPU+hiLUrO9#nu1L0#Gq`ismVulw!=fq@|~)mUVd};G!*J zN^YFP@%S-WG%A9UyKlKsC|OG3qfR7Ls@Q{Klm<%_whJmZ=5C)sKe%q9ZR<`a!|d%K zH7)KXo09xhjYxS~AZ>p8*iZ7btJG@B@JO|Z`}e1QWk;7h+^svs56UeM479puf@#bx zuk;rWYivr<5inQrS_*kmN=zLuUq+#5ww?J zB^RGlihD+?4&VZ+YuxNWuwGU65b^lr#q8%l^`Sl7wT+T&Mq7>L2HkO87 zT6rP^kGCEIBZl8HOkT1*}7WthYP_Wb!syI z%KC8F%JK`BCzfzK_m4*#HkZ@w^$do@7Ey>qi575<^rE@f*Z%?0fHz_7YYqW5O#>Y1ueM{YFUia z`7+eq;dpiEuU)KVCCwPQ$E;s*lq+sAjhW(Bo&!|oW@JPz8#91khTim`pu9S4utyI1 zoh&q)o109-Z9P5-sSY0U0H`w9D{dcn+n)d8CQtBi+yi}p7}Cu?H?k7IFxBSzn+hmC zPp6e!P-Rp^L|>`WX0hDTm**gGCZSm9(x-!B{{8ojPOr2_59lPtP@;wo62gV5Dp<9v zT0^?y4~F+OiSx?SFclPSfx)~PBR*Cy;xDXrCwVS5wTu)D45ZeiBI`sR$gQd7tx4Cc zxg+hC-cN8pS~F5WnqgJO@WDOIsec4ZHO@kM69rbwlqsFp(ciPnpsBDpqDYgoboE&B z)D1Hlv){(xr5|@Zu|HKWYLrCC7n%&1O7={v@Rq4pA;-rug@dK#^UTn@T~L!?l>}t` zrNTy+hnl7GWR&VJHGdLV_kSv}rt41Kc9B@zpcg>0({M+$XlHI$YIe0@P*m;wK6`z@ zf5-RlcIZm=NK|B(s9l8&e->QUJyiVZF-@i${P%%zy7?%pD zS?zN8+ajJymELH!vruM~d{x!S-rgQ<2|>8>5d=s>M@y?x2sA@M%%-zt(omkcy3&G5 zEe9>sUZ^*>()&X4r;Fl&C~%<^u(?`nZ`|4R<>l<5s~@C`KGaCnJn(3xYnp&pW{+-D zi;b*TtOX8*?MXhZJr>L#LA5{&KQ8P@Ow^gzGHS?09MCvM+y`u!b|I)uz_V-aTjo#7A$G<5>DfM+)R0CnDqkAfUsb8YGcH$Hu@B*}-kA_efSP zcxq@dKQNUPw&&PkvuWzWV8>F1%Xr#of-y2Y)2BCb81%>T^BD3(LMO(R--5!r1y@`* zjk={)y^;U2CzaAx#GtDPz;eJV>+Bj^MfhgDl0!I}P!#JTlw7UQ2asSM%Rl-q`jYTr zU<~O7Zw}_F(Z!zUyUT!IQQg?iYDuF(FHouH*Uulxn1{HSGQS7(PqzY61hXSXnT3wF zoy>;7TzG5lL*oS)HQJvkq!TG8)*75tr+O`Gq981Eb^@uoMV*DM=`R0Q6)oB5?uj~8 z`$8cABtBZ%l!g#Ftl4uC=eY9uGUxWGm(2`oO7~w&dJNpwo1Y(KaX`OC|0M^d1{%R&cvMtvz}Fqz zmeJZY`B-EghOkV3m2`-*v%gY9NzQafw`8iD$!iZTVXcqixzdiLw1s~x6K)|alnU+$ zcy5_fQho32fXW6M&FU=eSF~*#*XWq507t6At?G?FImRIn2g#Ql8vh^JgWoH^7HL5x zXb3l+1<=T4<^lHW4lFbn5Nkryw7^^_M zh!7xDxuX)ADR{ebq2o3XT@rinW4e7})BZ7zbTJLn&l8>Nl6ZKeT=%`tc;+T&Xl9!T zdL7J-{kOQ}++4oSGo;#;RW@6bFQ`iA0Lfp$k4Q#8ryE={ewJi9VCP>SKm$d2V*M>N z;Hm5Al*5nE#19X#99XM<-){G8K@etK(wL~jTy)_)fFGq{wgqC?i*G_`f=(~?kr#Sr_>JGhY$uq41~ z_=XLStZL=yhCMpLaQ{3tA(XhT+=vno^#yexmoc4XOX^_{_XxAx;xj9x`*T#iu>Imv`kECc9yZ;G6mN(jDm%FlZ|G- zD+2a{mc>B@DO6tf*O1)qu04UMrI*M;t*l=oDg=i4W~ADhh8Q>=zdz!-qyZSkWsne} z=}lFgmuhowyvQ|wr3y#6!%{TJf{1wYze_nvWuQ5K6eMbBSdh7|zA>=3L2Y%8FM%ym z1($9rOzuy_W7%E^;jV}Q(g6la!gjd9zT`lF)zz-!(S)BDNnS^`|3fF0cVf0QuZx2~ z`q$Vft>SzEnK<&e-d-L!8g;fyZRT&sH*`*#ZR|bL@R9dKW%Et#?)Tv=@7HXSc>z8i zPybch$18YlpN=K+N=qB%3*ecjkOB2=MDAcdy0bAFlZHc2JpU3(7r#C4YK{$#e|^O0 zN>Fk3h!9TCwHM;6?<_?VK6McZ1FkWDlXGaU5Ax`R`Z6IhNCELm$3RQe3M#I;ju~a3 zFR3oP3a%;%CN4w)m$bve5i+djI(%zr>>m@GC)+Wz$E>U@j-YR_QLT~Ep_DAGmMKLC ztpLQK6?$^`u)Q1A+fqxL$epFsb=65#lso)h5qD#Qy8fc#fns?^rOsA1kFy+GT8Iuc zC8Z2os+gWkn4SCix~|-&Eh4E5K=?{a4`oehXvfTX=sQZVH?LliorQ#gj+S~O;&PC% zC|D=qc$2``3vT6);rP9kPzvPBez$-&0Qmm+df*)o3bwu?zboV82ypjPa@HSS*+F}| z>x5vHma0|Eskk0|S(~zAuh$oVwjmYwn)on429L9V7{TYiV@<1+z~BCjrvZx_P1bjD zs+lGEyE6XxyQK;v@@Z4xpq}YGoy?~@XV7{Xa>r>EHVC1w9hWOZUe^ywk+qG9VVw=0XBJ2Hi1vEW4-XFT1c?F-lf=`Qmb|`D$Gb zU7IcvoOfSUcIQDxpf67CdHUkyu_=~fk$l5aI7#L5Ng+EBegm!WX(tql8DyY*G-j8a zUU`Gwh8xoOvi}Z&Wt#8s?U%j*Na?Je;SijroYjZy1Y=;-<>7fvLqoMOi^+T&VW2P0 ztr#`O?vyJlf1+^FvsvA^$^CE9}34grd^R%j6Y2SoK9LS9pQ_7u&;7Yx+!Wqea$bPSmgrq1$N?kLpzi(e zMHL-dmQ97-pW*sn&el^rKajYldogWxK%YUpFEO?+gP~81Ve43ykBq(p(qWa$i70Q&LzQvI%7x|4R6=eZPshS?eh`aHU;U2;XUA- zIaeXO8a}<|D}7rsA;dHSBzdF>g0Ez5;s9X(W~RQ%*!jG+tm3*d?nrl&Tg;G_dWf27 z`O50zj^fR?`4A0)IQlDkhqg@O;qd-~uqOPky-_9(gqImEX;Q^A;ewv0nW;a>!iH;V zYN&Wx>Ln2Au+gQd$H=%#c)|Ru{L0OQ=;r<E6+qu;t{Hfq197y z_~0v9Lqd)$C2>{shta6TnZh5sCOg_cPe-)OlzVgZU7tKl6_^d$!tG^neLYe7U!*@J zDngYbF6R!MT0M>kNPoAjv2J}3L*IQAIVsuc4A$US2HkG2JR{obC>D;W2};fn6stcN zXqGOyvN5Dmv;&V;ZSjQqUuI+K5~bYX?G;>H*Z@unI%b234~=B;{mnGsM#-1V`oU3x zWMq5OaD^n^yl(gU4*kf=L`EowGpHG3rvz}3_E%`OotNqm2^&(Q%+uA=;~pL4Ko7~w zQy;vhQ0?xZ-#uL6N=KF*nbrL^w*`)8B43Pa_>_?JI&a1bbe|o79^Jj3?7nar=*mq z)tcY-`XTtUvpY zf|0q&$X7r}78kx(y?0Q4N8Uspjm{sA~V>Ql$2ESAih+ku1<4taY^YA_4aPF z*ud>b)0`8#^)Nnou{m$vxNhJu7XS~&(B>-vZD zz!#>C%>4~QfyRh?@_Cg@KfT?`6dVjwfY_*USX@*hw`z*E|BvV|fAfU=7IZ{nJH1AW~Bw614kXvwtZci#LJEKJ*fwPV{$<1Nk?HkXB| z8#`DZ1xeriD9!_o<`n$&xDtGIN7IMQX852I0T8R5bJb@wI){b3!{&Kj64)k8VP)-qM3; zLXA@=*-Svr$^53Tt4l|P4DUmlT)<@3ZBcOPyTYtoqArTD6FdJP-H+47lP)Hi9pPjomViaioI@n ziA(sGR4`OE_mc{4+256*cTvxu*IisagnH`ud_FK51V2|7Mduzkj>aL=lV$5aelGT* zyP4BHYcrDR;ZH5h64$Gg*L%4Si(T(()RP?%$qVzz)ny!D9+}I_t}1F(ug7n>nIGEZ zPlKm<&^awW=6=kX$k`fw{q&mE{G!SWs7GJ{tlFgg2D4bBP z$bWT>SdO;a?DlhUHHV{afc^_29|6@8(7MHk30<46I?d~RJz4NSK&_fLOxQzjR8{pEDnB$% zz6aVMQj~kK9~t^220Y&=yIYuNHZjwEiyi(VvXO$;V&Y2Eb?j92}L+hU&fJa z=A(_crUx|OOmAZ16a0?spp3W750Fs(>%K{ZE+x0F%REe(lI22L3MU3d&I`^Bt$#qb|LtXQm6j28(^5eBs?W}+ zlLQeIelsEe!(4OOpsrTUT4sOoMvIAxsg6H7$QGb_uwnIlzPrqQO?J5li!yY0$Yll? zc#cRW4vM&5;`mzfbByh~sQB~Fu9-Sb7`Pw_VxED)>*dQg|EfK={uHR**7`P0gn{U< z6Be-J>#A>@uKgoo7AYQuW36x6k>xu2R+-+J4+o4D%UQtniA|0jRemD3kDM zg7@up8WmFimttZGs`e+@@^`~{Pww5#C|XO-$PE@Vmo)09OTUPUbW_TChjHzr1cOd*)5;2{T2l zb|<*UYPnz6T0BFrs3&s5&t8GmLYWg$bh{OCD}#$jh^3SH(TcyRw5o*^Y=b}n24oLXT}ho5;Ef+kToa94yvA=gWv|m zetk`WY$eh-{rb3QSX->Ugoc#{8XU6Xu-IorEbIYnn18+=_ACH!K{rCS&ID}w-5|FV z@&4gQ5;2TcKS=(9c;8n|8Ok*-QUpF@+$5M!er~Yl^V-E(Icnwe|Pt;)$pYwfpPZy9#NevS%0^Q%Gw*;UnzO>fKFeaN zQ7&j`R-p$4WwDeTlauFDQIJvmrTu*4+YRmZg4B{fFjt-wmz2of*Nwj6=xzfD*C!{> zDpDO%A;n#!`LG{v<*DCUql*>gms3opt|@#?s<7FA>-h)d^7cGo&h=0M(`?Ih>P;{W z_q*iZ(fs7pocBn}|HUj<1O?BqJgscioyq^&^T?e|dKR(hJ&$`|aMR@$( zyGdu^OLH8#Ie2#SSke9cn=R&Yg_&3Y>rLLkes#L!_(`~ zFW{m5c8~INd_&Z`+x|5PVo@W`=%IpZp*CoWK!-st0x%Nm?;tl=+bN-t0K!CLd4v*X z*|=_0|7_flcd}%=r@#94YxQ?^LqJQP4P_(leWQw2o5xAI1{6hW#rWyhXkp^uP`Cf= zbUy;c;lEyOwhnl2)Nx-gqT%Fxc`^F0S!uTRde$l6)%LK-J-Sh?#-8{*%J z3rqRQ``oE~MFQp%y;HcPH9xWV!)60kO|?ONVC?KmLe4bw+>a_5#bAryy`y)81(e?_20p8Sbb4Y?s|JA0jb0j#6cP_QLzCJ`vpHd4JZ6-e-)OoL}qw zy}*)_x*3l>9Wg_Ol~zBN{mtYs?=^KJjcDyEm6t3572J|eOLkozFB``c*~>Y|^mGOz zem^1|BR)V~|8NN**(I5re%<_*TtJQIaI9Mp@dG+XyD(FXqHUQ^j}NMpuSB61XDv8y z`U)}j8#XxwCB{M6iM~H2A{`65Jw6^Dt>z*+X)Kd|%iz@1In6G8l_1WJ4|xmx`|XZaa=DQu!cNqqQ5llK0R`zz*qJ66UDEF zw4kHgAOd-VZmF?tY&QyMOnVY24TY2=D)E!g0%+yh`&O#jC2kJmBD)`zJKK9RCeK7H z7=>P&3_89gzhDSS`n2o#KFG7#o_i7?rZ8Xi84C~AzWW;y%zv_P4gq($E0G8&WliOs zZ}6L_W(|kOHtc0&|GhyaFBB&vs$TFY)TRSM%Dgy)Doa+$fd7b_i71&$^mHV0L1uUI zs<2`GW;-gFbM0>4W2+Wd7G#7EqSQ;Jd3%YMCwK=d@y0L-{YH+zk|JmmOS0e(-T5Wh zKB&IyYn1Z`zVM3Km5)7>2@|cgIK~2jK#M;A2ebl~lf@cfZ9cC{p~Wm#3^FvBQa@bT zCjLWN#Slt6qihvW1!X^_#HfdFD5pvq2%o+Lqp0t@Y(df+V}KC;mqTRO3Z)jgik~)| zKUB(lYRK)L?)?9>E(w>{F{xRl?MRo1nX(ry5f*n1!v)Y5+sDxscdSwGhVrlPc!`u6 z8)fm->sZkXaPKO0mHEuU8R5YGKcPYum!mW*Wr8@W+e$#`;cpN?IBf0x6PD zet9`<1#CT8LWl&Sd^lMudvtYnv*Temd|I45OsmiDxsj&&tG&=9(1T6~=Z)$3uHWa6 znw#+GxJ;ENQKZnfloNjULoy$VFtyMmCzz1n|J4FKV$6x{n5)U4zn(bJJVACd>pQ@=st7n5@6|qlQC^vBJ&5j@R$eev;}C?5SQ`B%S#YZ zy&bk7qd7y7ZRh`}_u0()GN>2p#GGX7LY*4u(TJD`RzSR;-{mB(`kWa4v*DWu0*24s zsV?M|%3xV+6WWbIEO0?WiXCau=4nj#v!#VEPCNKJ_G=nKJ8mhuOawR!Ek<>Gv{{GO zkVT@RqH=kE05STgxa` zb5hIK7@EkT;UAO(p7GwOHa5SIv|ecBd;QYe))SHu0Cz3*^IP>~ARgi7@&R2UDYSNX za;i;DqDi@wpl(y~K%++~{+~I7Y%K=3fz*FLN zoFjdkupCqxsW|F|+NREqmyT*vMd{5U`nXdmc2~vnenCxz!FI$U634Vm5GbF-b*k@G z*xrb(*Nhk-iO~K?mAS@mVqfs#ODYzY$()`!#p~;AB*cP@M<_kB%}h){a@)f3u1!8~ z>;hU-Ynb>uP`qa-Jjoz%{#p1H0@1%bQVWlyJl^UeYw9TYqqWYmD(QyL8CDq#c z!#&i5Ek5UA1+$A&>86D*XM)VjTEuj%^Q)El)gE8UqQApOqZh0B|3FlO>PnR$P{wXM zL?Is-H*5x%&yR<4h?ab%mPdvUl=&kAsj~>2p*Q@e%o& zeA)cePC>j~EFUHrWjeDH^kZ4qPdQU9sjnXU6WgTZH+_Bh`|`95gj&Lj?ukJ{l|0-b zKeEEeB4iHVdbxYxUa?$kR?2eboBuT9f2wcx{<=;wC_x|C0rec^;WGvz0c=Hs8%ahz zFN!Y5&qAw@$$_>aq=5~e>H^h$eB4nd;#W>}-??Iv(Bq=MBt`ulV9VIrGM6eMYZK6E z70QjSn=UHJ9(o@xF7F=efF8K)&R0|Rm4fgxtofVs&I`GQl-}o!3(5^1(`YPL(wzbp z8FQ#L(P-1Fel1M$L%K)dIjKH};rxNN)F>H>lh81p8Vidn;X&x6P5qc=PNt$&p1BC5 z4}x`yBmf|!wCTg~H|AS$YGsG*T}OOqpNqN1feXvRIw>VRd~*U?zzeBnY+C&ZfuUTv zHyJ+6`}R)6piK&}cp!T6LhP?)k4JsKqCug;$9wN*$>iY=VGziuryEMU-;WJ- zbsWj;AWDr{xYFhVXFWBtjkcH;_zKHbu8tNx!u@wdxu>w7Jk$8?m`B3{~gT^NkBqWFjnxD*p9S?xv*SV zo0AmtJphX9XLQif@)BCN0tpKw8T!qd^lDPeY4$?Gmc$QLV@ONVF!}XK_m%M|fso;j zXGX++qlFexO*EBF!+$NihEjqj4>toJp_j7t)1L zEzc7F26ya7YHXN4S`&c*B$l{KV5*^b5rvb1U(R^56@dbGk zmSM=d%xJjouJcU@DD8IR<`1M|k3Z$Y(U!ADUiot>)!_5^&`y3H_kUnLmWl8ES^G(K z(6A>?vP#K4>afqvP(Q`n0f`}D^XIBg9QzN{MyZH~gIJhyfHg-!bBbc;9njb*yoNsi zMvfsOK2M@8k*js;+;Y6)GvnkWq>FGMK>R=F*JH^EHKqF7K}9;PTGrO28Q}r^86m9k zG6Qo}XfAbw(@KU!)xR0=b^s+~abyv=`*&!o4*=t8HUkJ4bT@$T619X#C_3=L@$=aZ zO-?LL`2Ni@w#{C3;%k!h?@Kh&x}A249cq{ctktpBIizI|?%?Qvehc=M1s+MJ$+|qq z9_JNGt(ABVJ_pSg@idRT=98(JpgYEM;+GWnMAHf4weYb8b^k6K21Dy!@m@6PvANv` zha=y0K!>X98N8&C5CV02(aL$(!gze0R}SE+9dd(kyEhiBS>0J|epQc#a{3sNAWl6C zf#VLiV~bAs^suqsGk9(Y(bkTi@DIdWT_5*v-lu#udSnXFkF9QrOy*HlH4+Onf@M?1 zZE#)#eno|Im`pPeXi9FLg}FiW+8v#ZmH0v=GYnzM^vV*;p1XFCtKa@}WbVQ>ZaqFG zx#yc`@$}W%Gw_Pd(s7u*qD%z$zRv6!2D9-Xk<$0f4D1ib)}W1cNyFoIT>Ht*C_6my zb-q~%nu*iTt1q}1M)$6=8_OA?+-8U6dPf==nLcUCny48c`C__P7i4L%%1Z>K81A$&g0 zQ0U>vTV{D5Up-XokZ6)9n5Gd@ADNMz2Ku;TACXXG^0XjfSEw>VTQTR?n?=s`#6xsT zkM2jX{%{IpD!2ocXSgm+JSmoh!*Q%s*$HJ(;O@Wr#GB;ng!HcCmTVNDj}gEfe(7dJ zxo$k!Q$p&dw3YYH(}+2e9xz(T0potOjF{Gt)D*`KJMEv_L+&I(AVQa7>5k2xYR6>N zuVz!eeHPQ*;f6iiuGd5bfifa-CmZ4h+$X~beJ|-*sDE#*#0z^J79Bi@zuqNpT9~=A;=V?Ct<5Gees+9 zxCJ=kKdtMl>__33`*rxj-gd|>(w2&@F1aCH?5~74Z(bC+M&6Mh9Es>;yUCMf-w#STSY-xU zERj}RUoct>%l@A9C{?duPr3mQW@}0qmQd>~h9Le@C=QV1Pq;@sF5HIxzpEtQ$)`F{ zFDA|=|J39+zIEWUC=f(6HmAg}Q!on)^Xh0dnkiy~y41!daPvk0uZ*NYcT`K~xa<~F z&NgX;LwSBAT|&+u@AeuUS9;rbIio=0FUuX@&{v%rGw0?rkovLm(l6rF3>hOxv^vks7BW0YRiHlEhwTAfOj>7*nA`3Lrxm7v!D@5^;PP^rC-lC* zJJK)uP@MlbK>9{Dq%am4_j6w2D_SJ+{gey!1vSM61r>-at+2xmN7;?iRUaAV14w~8 zHO*#yw;Y$<=RUi}zvr2RBS?sNt;uHbOd!77Pd=wwfi{g9w}T2n=Erm=!<`d;I0z(fP2$Pu&hagt$M-KbV>5FDvPPq$jB>xV z26PoCHoZj1)sn6Z@7tFsfP|q%IL2MI!Kn0F5&r%D7T#~rWQXBM{iSW9`JVs`aLgf_ zKY#8EBX6f4*R#1i{N*({(;KH({AL$_5JAb(9r#^}oax1XHq)KA18$xiOqI?Ka!B>c z`Q}#F^9=apr})F1fhBCJxZHt)ep~Q`;!SZ7f>>4jQ0G4iFX;F==GIaJ?{+y;_lK(R zMm?xZNUObjRr)J6usQLvaYnp539>U`fiX7*Z-W`tEG9j?kv&LVY^tKWy~h4INZFnp zW0$VcM(Rff5~4Xw1;SEWR%)WM3hM{v{q=5ONOPpfWUeD?`X4u@eMCtdBX`8RQbC^Z zaUKjh`dQP1#hk@H(Udec5sKt-7cbUIhi^?B;*KY>493c-rHJQLTL5lhnC>y6{2yo^ zy9|mQPV9)ODIW15lz)ycQEvvMii)>49hnD9W*EzfnGBkWx1y=`?*g#OZAq{ck`m$c z(n985o((#2#Fe69@2&1=Rd;dm!rB{>!j^T^&T$KyJ;-@EKWhsVH0#!&Yd%x1u!6nYB6qT?M(aRUGvHA{+`99~yZUNIVd%w)Y+zN|Xk zNHS1>9HgLSZD}8vpg?V(P_P~n_Z@n^|5;y|bl$pQ$d>{*4Om8YnfeC}HIpG08{3Tc zY5||)3jG8!waV*rgH!7I>h=y#|e!QGcGRw+Gn2XiB8wEO|2^)`*6XKavBkiP_+`K^IFgHKty^VLg;LiSjEd-pH2S{ zp6_bmm07kk)J4G|6Yg@U+->d4*F|!I)D%=c_iX_@Nb=S^vU9Xte3&&wgqxE&6%*6s zy=u|f*_Z^H1B>5)P;;(({j2hF{uot8e*OQIXFQqOuMwl{qQ63GA-PmQ2z6`mEqehJ z(up}=1d4HHx90!YUAC2Y==>Y-RKmirxBT>HP~X$ysjYU|U;2yU;g~#a&1VLChA)!3 zIf*^N<|g`jTwY&wb$_07#A1(vC(yl^k`uWB)W}VSR+g2(@ut zXJ7>`yY0eB`3yc9jxwH zOuITwZi1;=xrZ-p}f0ph)4_SJ7oVQqqUW6{bS_T|B zp%TkKcnXM|dTtZVc37D+ni?ubs?q%lp`eDG0R~*On&Z(N$VP(}En91o#A{OcY%v4H z{$E&>K|MCxDH*{ge&&m{z8*>{_0lh7x7*Yx)Y)v7tKSTmnr$YTC;<$gD>Mme7SctH zWlJ`rYFXo71w0FH&PDT?9qU`wik6};4^?O<>+4xZs&Q(v|GAQ%^8cPo^fs;3iEOs< zVkC)m3x*S`U%fiQjgWsXPu-Y$%byIbE3US$d7@4CUgS>(U)~HmOw({j zqB(FOOtkxfPB3TBi54o6{}nF!kG^sG@i#S16<^)X!4So3&v@;9erk0y zy;$6MxXJI2nhLgwQGfKG?S&xZOuQ3fE8XSF`@8+-$8VS9g_C5jbf&3Jlg#1s&#a2p z&Ghr07XrjR80I(9tfWV2C8TDgV=nq}=8C^rulRqZ=5b}+jHtMl+9{oNx&5hhN12t$ z*)CE6x72X%z~1*Je0XEo))G^!pM-Rvlw0VtX9D<`)8_XFYqlbd*DZsqs^y1QtjXW{ za`vq^`Fh2|DVl9=dtC}A+e9Gk6xo+p4!7S-_0H; zsQ<;F>u?|eKixYUdtGx53S!Ij690yfFRMj%b}QC-p|${bs?Iul5W642=GYgUfTr(^*<}5n zHdHkC+>QrL1@oV=d-3q)r0f9H%}g-SWsm&y;T4Vh+wuU0USWl=OMRa^XzS};_Er<7 zmwm@UD=c3MDDTJ)I0Q3=yabKzP{$aA^Au{gfg3Jyne2o?jTS9L-J*4(ukC)mxcpne z3dCsrmx{(I7K<^axf{zZc3fjW3gYl*(uQ(aNVE{WBSzLk*oA6g-iw(0IPPub8149%@%0^Ckj*hCVF0K;Ws?YkXIQ)`b z?LHYhbdJP2PZnPtOSKp`T5K|KG%&KGk*#v~ug5QQ>0}cR ze9hSJfwhec^wD(AU6Q!1YTS(aN)eLs0Ez+Iwf@*~eH=H@m1J$}d#c@2t8@ni)6F_# zs_J$}F36s*Cr$t9}6?s z8Rc!J6$1$$+|3bLdW8sIn z4CN8qw-&nH56yl{6rwr*`||FW-RGDM1bOGiW-zHNmb+-mU4JdWDsm1HVfRERMf>e)fhhQee`t%=`VS&UNcc z3H(R@oO@ZgLcoS$UydO)#8vGzu29(y&eFc{%^^?ff6|z6T8w)gPXX2~Fb55HMjZHovXHD5eE0q3S2?VDckXdFxc_8q?SWx zf7nu>EDb703OJ@g4W}{a0A=FU?{~UKf_GJI7kd>=1$3v*zjowvJQ>jQ7X>gS$Wj2OeRZ>wB3@xS>-TFH35q zq>z7lHgRMu&~TPDsTbkiw`v9(T8>-P{Ct8=v;U7vj>1DhFaF06h0Uo^^Nr-H8`}fv zvc=6`>2rSIyyG{A?!M7W1}|R1?6IZ~XEx_%+6*K;9r?NgCk;>mmDRc~iqyfZwY#z4 z#4jvMO4o;FDxxfXH;3yFS+^u|nb}$Ps?VbyM+0$ehO)wL-#H!8KKXu5#`lU4w|2wh zb^VXqQr2P1%~NX&)$um@&ODNeEw%<; z(+xg*&ev?j!otEfU|#6z6wt}ALnY5U0m}mk_RdanYO;|?Fjux0J@nEekSzByG*h-Y zp$d+aa$6yfKNGBfz~@1QE?yGs8bBp%Ds+gAACt?Mvjt8Hs*bkW?|e6r>D;G9wj9h8 z84l*)xr9Ggm}aFho64gg=R$36CniTXgm>PJ4DawXQ2Cbuveo`4YmNgcO!~t%Ek0vr z(*5DzP);z}?GZaHwK&MAKmJMeB1nX{*p5wbt6a&)Qwd4eJX|60$ju2+gRmc&P-Gz2 z)WB5ZveU_aI*PYxCV=EPu^(2HF97qsvxbaG2YW}{n(8aIcakY+^>3`NmN#`k^lY>f zGj?P@SPl~DjYI%T;{INuVmC&@Gj_RZoz$V>eG%+P`_p&ot;f>&lfaji;nx_3-F0>?^ z;I&mvl6I1{l~vkY%a6xXoE$j9vbA%{GY&d`r<$y}SXvCMYxRU4Kq*9%De~DG;!e(H%Grv1kMsWi{r7w4TSv?%sT($Z@sKZkMebld;iT% zhzJtIc8kQMAxV-Y&AwU9^UQ4}%{Z7|qPxZyHUXeBbz5r7=hl5+|D8xqR-JM=bo4@g zXCE!`#^sHex1YeSGmZBVp!#QcL!l+7OLUsmxFf=w$9G4wVBYO!&an`a9W7ciIM21q z!qMpjR+4&1A|5u>;umIQJy{m0!j9^)xb#QN7}wK<9M_fM%CL0eQdpmf1S>)s*mHeR znZGXLE45_OP1>M)3$!1{xmEIcWh-FLmh<7ds8M`5=MqCbGO;KvQ9pEj9+^bK=X-O= z_nB{Wq&$hwvka6SO_mZP2sckxV|7kA6fDs%Gkd z_*c%2HB*B~>7>6RCBxh0lvOa7L`DG;8TVEE>sK8bhIn6zree^X!rP23e5@L(IokB^ zi5D}^KuqaC7yN+LXUx;xnDF81S&OeoNL6G*P$}=h@}IT2Mo*iJbl#P*5;1!}c`iJ5 zI`%P=TrdlO?3lL1cwKWk%Ks}=k7@=yz)5Scx^T%s6fuw6`oK6bX76{gr2G7c&F#=8 zguzjV3!34s`^~&Q6S21Di$6FnbmXD>M|^5I7Vm%mGmv;W;J6a5gLEw1tipb! zR!rTuM$b=*^NU?;m@is z$HqK3Tq+(6djXjB)OGnVv|@_^Z1QkSSez@BvY0mERMje=C@W7bOhI(0nK)Vo*zT(Pud}o0bvQ8Bk(CLFOFcl6jc2r(iA0{#dKa$cQ^Gp-(D5Nu)KYR3d5a`7Zwevh&Il|nazU&C(o7kM{;i;r;vxP9_-aWHD-{4TS?25 z+SEcXcL8?k^ZiKk9x`j#HJgDee?XXON0dWU%+h$_5QYsSLA*KHLM+{;T{%!@NIIN| zFIR33BmZ`*t(B`(y!D{%<2Lp+=A6j+1H)si$M4#ze6#oVl-1U2Kw8Lc1RH0 z3rgYfuo6Ii=5;In%WytEfyK_x-~h_vbh*0*D<%M*U>nj@`j*qvl|cg0^1v+StOYLa z?**{Ht`su)L`8@tk_c7DOjHG))MQ?4?=kgwtAWW2QXR&=+0I1tYffi+LQ>L#z2o7k zGoGVRvjJ~Uw(}0SUPTLo)Gs!@yOh=3Tfa6}_~(lK(GN9~BfOv61p${X4Haw!4l)*M z>mS7~u8+^$6LN$?Eg|H9TxCp??2zUTthD~`Vy2a*VUzDpO=bAu46D%pgg8{Bk8#%; zgv#)k%LEWd-oBi!C#M_5^KgIzNfce{JfgoxnXjb;M%?c#vW-!s7{fw!NUz?ga)t@2 z=T(;g6;;(f=+3Ce6XW+7rLx^go~`2g`lN6q+_^$Yq_@A3A~OZza2oWFpGq5QU7-~3 zAf~Lb9erI^L++ytUVtjJDh7jNR5TIP(l+tX;9B))!;v?=9=9+B7E`@ zf4}d>-X1dbi7hVw7UR4``_cc^1pupD3~c3#YzdM~DWwt@;B7D;`9FkxWl$VZmv$f| zxD4*@4ncyuySux)ySonV8X!2qHNgj$Ai*t2a0xD7=iS=culCQ@{Fs6oX6T;obI&99 zIWqmQN|d8Jg5#Mr!yVVx@kmPzmg`WWkBL+hRcS;7o^#zxn38vhVtNC9^~EVNP}TPc zz2KB_2m{cj=nqf1hgo9Fe73n})kRC~cK2uFTHYYHybNi*26C zm!f+nRi#7l{IW7fQS)I^{{+8wP|_@*0kRwD3R8mU`003V1V+c_LS&TDpV6S88}xvH z7jjNkv~(Pkn7BV3^!f>iLh8O8CXml&j{xGKu^F|$ue8|VeRd}8dzb`*UN2J+Vn?NR z#fl0>_k6MKWh~D~42u&=d33m0n!K|~!2vQWmz=|`yN726qi5?&N8C?Xyxdw%PQQX; z8c(LiKXrl$TSA6%)qIX{Sc>9)4c^*iO!!$)dq%kUce)D*1`N-2UoajgR%{*EZq@OI z3-!%pmR94qNUVk#P2dKXH)e%Zzlo`L2#Kt1e__uvn#2ojy5}wI>5C7({H9{G@jb_F z=;jZ0tZdTdF?zn zrq9%65O`|}!C9n&w)xG|?fTn|o&HLD#*!-qMZ{HG(tueQ<3x^fZLQNIt`D%Q5%PJ) zSE*H8t=QFX@9c;!oWnpcsS*yR3#Yq%uASY}B(4c|HUEiLPlF!?H!^;7dmYS;oduaU zO>P;kt##*p2J;2hq1?9~4=2B_H)vsg^Lh}i)A2a?ePkfR+YzF~{pI3n_1mn`>O?Dp z?tU*jV$_azjQk^Vj;xUp#c`i@KO_rgf=_-+hy`{3CUPi`5pnwzC(_J;(fHsBwcP|y z#BPXb3g^Q`bq58TMd86fP+jrM&n4&fj{Lt%>HI=XIJemJNYtEyB0t(!g}$sU13Dy! zIqtk4$L^?BVdJ(tx#g5#_vOm5_7`IFp;wMCJR zTl1Iy1H|gkA9iN7KG>qV(<{BedpWzbvAN{>`=$Fu*nf? z-w`sXMt8dBUlg;TDZ6BA__3gElnaf;$Jz7xXV2EZWJ@dXSKk^@bCl2!w^GZxVl|&( zhjiuN&K~QhO=ZSqs-g3T>x8YOk_5%~y&M@0uC^SIoIfKt%@b(`wZKUn>U>yEI8krNUU8|@spStUJbb_k%1!G{IN+Cag>uRDkdilA8#|y z+po1_$U5iCdc$EQB>41DzM;HSU7W-qBviOit@X`%mOL~x)cbDT3mz5qO+?>ZM+Xn^ z)b5@Ky>*#4VqSvRJ3Yi|Gq673KjI7V_X7Rm{}`6rvvO5(z*7%#mz9%p%in%eo({{C ztr-k;2-tO$pAN3ky+D!#rUP1VQck<+q&tT@>^``k;Kd{e=3S!|IEtE1@K9cX$=l#}y7QmDQ=oOH7WQ%wy!`4a!SYMHGaCYbe zVhhSS*SgJi&5q|96|-T7T)C*2v9;7n+vSMr3vQg61t@b`N^KjHHr-YAFgAuK0EmLl zK>9QP9@S1dv2XB*0Y24lZK#4OpEqK+lGFL_k!NanO`^)B{|5x=z_Jz&`GS;&D#H!O zG1iv(;H=q+|AT_Wa`y3(3+HU~BXBh|p^akTpu(dkMV>gX2Pf zOP(QT3g39W&l2>2Xwd1NLSm|f=-!bp84)~dzUTkSw9)%YWzyQ)z2r*HtlK5Y3G35< z{2mH~+TnNSNVh$_ww8Cd;g=*B@c3*#>}hC7ESJH!eLXEy0mMMgJ&?0WB^KJ_9_!?* z0QU$cJep{up@xRnDy6L^!Dydb2+PvB$nGjJ%Q%9gVa&* zVRCd24J1D=Gg#-3LFh)Pg>UUH{AYL5(Ak)08BcfT*Y!a!{|xfdKQ_UJc|R(Aq<*;^ z5Uk{}xwwg8rlh3IExA=|*6u|u?{XzRKT$^odk_EC#CD@MRKWo35?-=1lnZcokT%4E7fk4`W6 zOd=tgi{_pXNS{On{0~NF$|(ai!ABlqI5xoXOdy(1i9#Cpvx!04%)y3f*sEQ|g!`k=klBzp|9&G9v2jPo5GHZ^g_NjclSLbH3$Qh!!m;O?*NlLCeEdI^5^91u-D2XT3`e5aT1Am=!eu} zj|T_j`3J?jlK?-(e?9o|Lx9BE3?@D5AwdKv*Gni8Lc-@k(Y+5JKBUsfz~#gxQ*6s1 zAR`Ctc<%lEss}?XM-4tZ_~t(?@hAl|)03do(#Kk6lO>P3^Oh!SLov$V?1*#c(i7u7 zxo)+?gONL-x7)RAJ@3xWJ*4HTsF-*ojE)!a&)#KDlf&)wO2jByuPXlYE1F9aLO9>^ zaeZIL+BPsXBUOJW$$~@>MeE^?9Xf#sD&?1fZRL0U@?rgl>#;RXPo%v|Es~JbRCF$< z4aTAJu8xjNz?(kP<9An>KA}xTM_DjHz-6DznAi9Go8|KMw(d1}@6$11$Ve)r<{4dZ zJuqWba}w{Tin*3XA-ZOUh1<3?X0|1>`|%10N5xxD5FZJ;#C?0Q@|bdyWornOvaBm8 zc~$u%{`vAf$Q5H}o7&XtUxu8#1Bm6J($!#xEF(Lc?x>_zw3Fr+lrWbS=Y_9hTD*bB_>TojqIkM{RZ;ZCx@QYJ-znAZGx^EkTDfC%`#Y zL`#0Hs??qzQ|=A#)6q(Q%Wz9s^?HZ@jv0uSmd@%lrCQs10(X;79evFaAqs8}D2B~9 z9*lqbVxv|swg;;JI%9-i?N8>SKVUk*wY67HZ0+q)VvK!h;MwEh$A&U#Gy?m^*Q+V9 z&v&ty@$;6dXufs4Eu-vVPc4IS6{i7v|8^1p zo0Yck>$Yd!%J1CXD5Gh74g__iVXsn?MLWEVfsv52XZL`i5Z`0w)M$n&5lgC2CZngl za=YP|`>X2hFCjaO$@s+CjgKJ<^Ho5%+lJej+s5_A0o~oFvp>gdPWI641)+a0cpj&| z4x@B;9icJfe}ewzrq)vu$dU46ZcddfxXWT3doA$kwEeiQ3r%vt;jw)bp_J{9aL|)n z`bAhF+~jhbQ{nQUt({$jM=H$Zd+2V4FF$9G<5utVVdyy(DrY#zhlD=5j47wAPvTHG zGec+eWbFCV+6vI##>^-&j6G%*vVt*R^n)TTxhhFH+KF zw^WDa=sNc2i-J8+mAhj)TwNc2DM|#p)A)3G((e&pv&u=&Fw}R4dTsc?0;L6%AtnWv zpmy>k$I?TY>IYmiQU8_;Q>8W>lfSq#>)oYcsWP&2mG<@{Lfj<7;ql%Rg=r`e6S_|& zcq@za_WDnpyyU|>a~<<&pwVBAXARUGyzdv!ctbiDnQQb}iBnp&^VUt?1>A&;Q8_L* zh?u{nu2!@?envF4{no#$Ck^2J% zpMj`9(w`jjP-Lj3;L-;3F=^VpMPf9<0&Rk>irzajZzf{75lKgH4BCSX6 zXrZgiW4?N2)NO{7E#F1|OviOSLK1}82`;mc`L)iVSz|2X#;q%%nIeNQDrmS8925{l zh)8X*Rl*iyHI9bDkNv6B7V&cWZjsFARYRMV4l69Z#goFmyOn`A45WvOwQDSbTvy1A zV&k$+TuWjL8V~qWRU!WIZY-T4;)}Vvd$Wey=VZPlY5ETt^VFUv%Z=Yc_wzKYv6}tC zuoT7|xicm+!gfE&R6#I2G~3=6_A3>DuY$H9@5cM6=w)^DRWnV{T{0b?yb*}I!GQ>x zQ#2#N3=lcP zTIseHD+PaseB`;JJWKrSR_KoyVrf9L0Sp}8Ipcjc*;^pTi!!4PutUz{)0G3kxpJSc zv>eyWNvNk?@0_l#tcV}ZjPB{&l)4 zsiFLm))3!|Z(m~HS+gzfU{E88<{XtyZzkmB+q58tqXRv($Pm$qhjp8!eZ~yMm8eQ6 zWtF}1p^86$y6=8zA}22IAL42VrALvL)Az(~_7fh%kl*v)l5>f@DnMO*j|fi$ z5!eLBO?oZH&k z`T^VT^%)5&ca(A{qs7yL=!M&s4dg{wzgIqx47pdDg0zQz)!w2Qsz5lfT{>5( zlIW4RrfNORjOceep9MVo``xD#dI!@qjr+sWBvYURZvVTe=K>sD*c!h-8}vpbFqN=B zGIGHC{=O>FA3Is9HTknz-JBwXo_8g1lk3kfY(cY4=#VOMEI9iUgUfWI|3e5suMEC{w z5863AQ_)z?kDK6f)X=;wEXqk67R?j7c00EO*`UM7k~dXCo~}1BOI}$Ly2NOSFMjjE zq1lwub2Rs*ZctR2Cx0C>rpKESjuuT4d_1I3Ms`9FC@CufvO`gi2)5#1eV;zrQ-fjP zEWEV1n$2E%=MPV2O)k@rOioqDbkaB0v5`Qp6cR1Vfo1Aw5Gu7#APnriS@F446=@pt zxzMutBWH9|Uj^T8^-d_3H2<*8a-+m9wMnTQ zde&q6Ze;UE?;dl-)woBrhTGM*cSxuju~My?8fZ;~&R zE)-Dm!&=l#kNY;iX0S2U*PKeibn2diOp*C=OV~mVo@Hgr^K6Z7jB3MWglJ%8YxGak z7fV!Po=d^H*xX2=q)sTPxe(5IMmBNvY%*?ct-M&eusjS`{hq6bhgQR=933|$8it189_PUo;2rsfDn%s$4Q04m&FBU3W|icH8dzw8lL_71`FUh z^v$qnI0E{=JWXMOKW~#EWkaGeY-xT<>O0OVwWRcFQdHyu%!DDYvefB{hSHexwj4P# z8?_Q57N1b^>Yy#0lt}nQ(O!&$(xvn$;incCHM?(D>`KhZhfb3{*qN9dmT6{5bQQOk zq>M&JzkBnu-C|RIrTCa95Z6lO&}!s=IrOWhe{gWnu~w?RIZxGX@1xTLd__fnz#YK&pM zAM2cmp}$iFDNbIOSfuXfP7d}7uV!M-J_@DeM+zDN?5akS(C@TZ?9!Ak62&@8D!tWC zFxKC=@f2qMAd~ZaZRpe)luFfLr{Y4wv7(9Tt7Qo}>XlY|M$srKR-?5zQz1lkaKCN% zm~qRor6pw;x?w)(#?wZ|P3fUb%IHWMTgdN!-!MvFRz`@;L4wKK8v-(hS;GuDJ98up zlf2?R1y0!Q_9l!tV$^r85I@hG#HQf>Ez16S-r5Q)}Sj{#-yAhds=(& zYfiG3dQ|74;;4n{pcD)lGdb?I2tCZ#bmdWtWSJQ4CISN=b~DLuB6_~mMB7M}Bwayk)7{8w-pEJjm05n={w&wP@>AZI-2<|v2tPK{(X z-fnQZ6C{;Nxq5;57~F#T<^EyGD9FIO?u$|(^J77J`Vc(NBJ}5prxQu)>A)KWYInPv z&^6`q^s7g%pKYG-A~sE=D*RNiBPec*6Tx`YxCxfH^3)^VXUAjAb(_3g;=YD`7cQ5=qnVZrMmYhp`7z-W+>QGHQpe?blG`snkRpJF zo}NBDe0Dg2z~$xd((Y0pFpH>;{lNKorI|0g**%-lToNoZ3j5dkul4zCNsk<2?G$N^ zEytxlGBT7e8zwuvIs%UUcts(@#yTmjs?KupAPcP229_b$)DN7%97}FCEhhZHIs;JAfTo%gtgphy!K!}k z?zOtZ&R({a0bo2W3~066=TqS8bs-`<9tOs)iXSd$r@Nb91yoy9BrJ`ma_X#ysM8)O z$zKnPLIFMy6NyW|-_1tl!hmeEq<>P>mYulWSHtN@sbc0DqDmd6cu`oe+H-xlAZs>5 z%$UrosrYHM5`W%tK-{IPbh>Qd7z=8^hgzw%N^-azMWX-#Ad3b~tZ~c4aPmJPdZ| zz~)I(uiLM!5upkPi&7lA%VbE;@s#4%?0Lc?A-Rul%vat2Yfv4}zJ8@&3wnF$U)ZU8 z@sLC7P;-nCF0Fgdl2Ie|Pn`W!C!9yW#`FZqZz2l0z4i3J_yJpzqit#VW!VWBzjr=s z!b?O%RKmXEHZ4HYt*!2xLb-O5Qe(r{-+PHj4en)|Cgzc)&y-$3K5X_M!qVE>jv|rN z*UuAE8mBbga5$6*mWMAN^gO1?kEJt=VyrY5C>Qob=g^|%Z*wn~VkSOoHUP2aC=|)6 z>>Ql4o@-%Fy-G?^>l zQ>Q00fX3uyQStC=BkA2jSh+&5srTr*XoUrR=HV!qYAE8=RxpOe_Rd6t_0wC;e|rJ? zhuUfFDa`{_bANmRzjmGXGOS4gX>0we*{G|3@()9)+U@X+$<1r6Tz3o zPlqaaUqp+1%v6ARWuFhAYQjT^nLE&bAgWvgc5%b^D8j)^V3c?1xrD^fm;^GpgusRA zks7^ck!i4hG2gUdKd9C6bSe2@StDy0JZ@Hj1mU%T2nOB$vbuaYDBQgoXTc%hM9e{T zGPtP!2R#Jgl%=Nt5eO!Q@`uyhNYC{Y9|#Z6rVzGWhCw{5N)_KHw$c_4@*yQtu8Od| zKRefbv$XSv`CRFj@h3hzx?Kqtp`-j+n=7rpM=Vh>F(N^4`fBaX)ks?f#MI|fG`hVI z`^i(md4=(+teVt}&Q|ruln;|cf(g&>U@5*|38Q>mhMxperT%0)Y>2Y*~T zuO8&74Ppd^o@n5duf~9C%A}7@DXpj}@YQ?^va?BPtyp1-&XJUuh;3HN=5swfIljUN zDhgYi+TXqR`*Dy362!mz!i3S%`EW%DV=eRu6tM`JLVs0nzr!NAy|MMO#ghbDpV+an zv5RH1BzPhP*JJQf+^u=~`_vqBtocBBF%-cq|qJe@Xn3v6z#i zxtN)AIJe7uTb3(F1C~+Q@Z?emffMz21bq^N|IB z9@$#AI$UToC0)TPhAh>Jnd)@9BLfQyPTdPYizEt2+`h}?sGro29adC!{Ujz4oIwit zth|4#WfVZwOj-39TCJGi3kKCvhV2|g!THQI7;JC|@?xn?pup#-Nkl%Kbt%OsS)e_(rjPcQod`oxZmk(vg)nzOB0U_lUoJKA2MCYM2WDjdd zGBww4quYl$VVh@0Gu$t!H&NUJrhw27QT6#0L(2@rQK81x(H_GA7H()8VL*0@xTs%; zhw6a@2Q8cpIbCn|=hMkublr@DXw^E@a7@^9XG<4Kt9l4Lm<$dNk0K16oCS(+uET(x zVba0qjoTv8aJNx?vS-TU%%CGTuo6Jrk%>l2CgA@Di>G4Kn*f8I!)OY;MF+ouTd6g) zO68rT4Bd-n3E~eI@Qhh=26;WA#89Ym$0!4VhDLd;T+9$ho|>q`xBV0fRD^LIgFzEM zz70f3dT)imiYwS@#qDd_u3M%m4rQ<#x#Lr#Pg?Yzd}QI? zGlr43#JFw4iXB+YDiQ~<3r@6JM-&`~4tZA#FQz8vwz3KGSA0IwlzS2C^zTmA2u7Y# z;78i%a7g@MrLp{Iyp*OX<+BDt)JvpkmQGLwZ`$9^t?XV;e%un`jEsye0O)3h{1?HNImAkUYU0tLQ z=_2yxqpY?$;cT$VDw4-gt|Xntpz4sz9qV3-1%4R&qdTMTz}&#>%E(fD(fqSl%Sgo`Kz%U9Sncwv zhl_ms%@Py?jOu+--1n&krIaU#y*Z7;t@T4pkID)gCT66JsMAI1UH(>V7OQQ~CaC2* z#^$Gqh6;D!*HzdE%T;_NxW$S_y_+~O|JP18^r>o7uV0dnQ+8}#$J#YsTW2?XWXk74 zHxaSzN;X6wS?LSvBTWTzaQYMcb`!W=<8OW9LdsJAAzqM@Y=+)f703Ff9&?|vu*rhEM8w2cJzKwk)|kf`sb5X+hgB~bLapJjviliu2!?n7}=jKo+gX!nDPYaa4o8i z8en1jylZ(k6~ryMCMI3Af=Brjk;(ewS({HbgDeC~%X~ zwqyaYiRe5x?DH|s4_Ch()plZS-JNQL!Z!*1FqSCw58z`jL&2yDe7(uwe5 z0H^R1p~Ik-^Hz6YE%Ax8=!g>l#pIXUhWu0*zv$SMSBzC$eoK!wIM>o*GunI_pg_SHeW&lP5{Nu!0*b^n&bQ**t^!^Jc0pxrss?Rrh5r=RjHPA)EuXi4j>4!M=Ea=+0B`qwDVV&9cE9PSdOdvD#Z zk{e$Ah-U!pzjLvqzy3RfV+1EdnF?Q0BZ`pRmMPt3VfI;DIpXERP^C?MxXKDbw*LF7 zpVIxtT=l3@uiwp6zZYpiKN^Qu?XWRZATz-N#UmtmJNQgNx9UqC1^G0*sY z;Ow5{TUASEk^b-v{Z)RGv(sZE`-B2WBoZ|v&ULM=Tq?|$ElY+NI;-aSWokuT1_mFQ zuJ{Wht>00ri9qlP1M#6EL~Yw6qacIMG)&_>Bujvlg?akLCh%)3hcUs%i3k6!ae=@gUfoq{v-1A-v~~aN z+=(wl$ROl*MZ#;DH_F6V8ZyH7-4e=Rvmj6fv7jz;k974GWzj-0yV9T~_Wc`V*hhWrV?5<)BD zW%bT>91OB82)DB`pxmHPT1|`Mk0HJoKv2L?^w1>xC4`U-bs471OvqN2F-6>cISExZ zB4zw=Q$q%3mAaYC;QA{`(Yxk>F0n9qzi>rI-aNV(w=)AwX=adZQ$>fjaGcKP!$FAX zU;N^K71*B?Yni+hFRL);^#{0zTXi}U&}%l<-KEVB!5U7Ln{rx8&@NfXPlztvHN@2! z@}lzITfqjV>_?CRmsGHQIA;TqGr{D~Gw^A3)AaXPx>$xZc|s41*TL>nKT))T zQ0z>!r!?i4ZO{3mKJMI?qEnUPCTq%6^-nJI&o<;3sVqwr!q^ZNyW8!EIVWe2XZN)n z4kL3fzNfF&)+2xFZ%qJhbz)TJR=S$fL=yHp$<=t{kuX_cqjhM*$6u~0NVor>m#2f7 zS?RJ7q)Af4@V*HJig&rKwRIG#Zn~8uY}S7G zuiFS2$BeHRcTX803hfNa(;OH*@8Fa`i>YHS{cYKjW5=T0P+WwGbs+b;>yJQmXr)J6 zd?^3x?KjRvYZfGY5{)lSd4@$`Gd?aJ-c-s2$5}yRW-|rNn3HAg}0_g10amGfUJGd8wQ8!Lq!>jB{hvn9GF!R?NQiP0); zw*-ZI{FVPn%@+}`n;x~wCi z;HPt>EZz~UqE<}N8WvElILYU1+cd4LDx!Cbi=5>;1_5hZwc*tEjZb?Y6}MNWN*J*i z3wipF2dUiJaCGDQ2$i zw0#W2OqZaGW@YYY$uwl-fO&8gfG+bDX4jRCS=&CB3@R;0I#X&T!Z;grIah+sTr~NZ53~Oi^Q1KH`NX9!qy(|zN1V4%wlmLW|OHqZn3IZRw z4wW6uB&6TJs7MzVNK@oSDFySd8qY0nBrMq7#i4OGy`t_J0Nv98mcpZndVtAGFSI@% zjb1Xdog#$A zI$}fO)$M!%2T(r~AAlK5Xf8S^1gB0ghVGm;x^=Yu;H`iGo)!)vk)Hg zQ4*~wLV?OGx}I=#<`k~at^+eM5Bs@J#IB4*`4zS^`+xja0gR?qIorAwBxS&mibNQo zV@@CK{&q2d+Hc`8Lgb}QWvxh{qho-mS-***b7DD2`O{Cnf6}ydLFX;hV^S3KjkN*mOi!(5VD-hoVBgGhNEuBl7hKneakT zMv(+kMveVmC)M3J;0W{^92wDbumJXl|Gi`dK%A`u;*BK*x&}yDE+33#1M;Z2mq|q- zU#m%}B5mVOxAwbUJx60TWgs`p?TM7Xb+2-HyntDAp4G_WBTMk0F?ex(etN*9u;d^x zVa+YN0Q0Pyo>ZI9p_?gWd|F`{4HJnV`DxpdTZ1%x9x3q++-ss449nF*6B(as@XC?H`hkPZ?>ls&I}&9G4$MIWMqj2 zj)iuG{1U)aaBNKoV3vYonRRGer%ug%L=XVh88^8>m-n~u>^7|M)pkMVsfuIjZjVYq zj~KkXyyE2WLvP5~PCM;7mlGK>UqW|^HR}zT%;{-K{cjFuUvxct^5qLYa}aa0X1iAp zt$jHk-b4@@8Gan_=6%wfNSKHmoDMA4f+eV_PmyWLP^oqJx+wYwH4RsE40msTf1C|& z<}RLoSGir&&#&vgONfCLEHg3@qSX55*nCcvIc1Fn^ID3AC-#W~q}^*T_C2*qX3-$E zsvXc-B-ZExK0oqeeadb|HtO}ehqI37?bdu{GGx?A>Qc?z+W2XqEFG!YV?o<<$;mDQ z@2f7AWBO1Tx=iwV0SiPmH;!1*#*IX7D*OLAC=3eZ5==*;RBx20f2rz+1^LnMYM=c4pldG@IZ|WW0^&*1^~BU9&~zXiFN^i{4TjIa0-HazrCMOv=g;r z-`f3i-q=Bg${;oIV3KKQ>|Vbf~d?}?yF(5bqZ~^=NYi<+Kh*ixT8Ri z@G)HEnmL7{7_uaFz1InWR~#52fb8wWK!mOGXE-My5Rkb_^}Oe3{Ewj5 z-&FY_zzZ1;XbigTEz!!Ub$Jn$YWhiv6;dh+1RK9v7Z@;{KU>Z{JY{n#*#nwx@$R{) z)40ulsh&w*)&fs%PkSEbu5QHaqBr+DFAM#pVjd;wvQ)R{n=Bg-IXU?J7vJBPU^*zH zWn#Bj2CQ5YuUOGN#O#+eH)H-2iRwD`@f%V500pk3fAzWAQPOD(?%Ds6k{Wyqv$?c# z^?_YSYxA9j9%xQY(ii|Drr%0kW87^G`vQAL8Ot#A%*zfCTL~tq{g=Eky?)mY|8`Nk z4ANO56F+-K3gCTE?f&`CE3{Ky`IFqi{N@MQ62gMOW?PVuq`AWP+f;NIn)8cJdq==n z*paJBm1h;(H|&?bdSN`A-p*!%y{8zPd&9;4u<=C?Y>BWOTt&D{>cRcE!=T6Yz?jx;_$46kw--YYL9vQ4PPx zgG?8`YV`k+z-F1_>E4ND2-ld)h}ACWZCz`5OIvsWqBdjEe^B~J6|{qClw#k%4*tp{ zcY9=izG^y>r(XAf7AQ8_P^1>x$N`r8~f-%c=QIckjE%u+DFb(LIG?eyj!_9vf&@5dHM3euKgO=>5xLEB@cMGiTy7`iv6&0aSt`rHol$@7b*qB zd;EpHust)#!pJ`TiMsz_oLclx(`4#LfU}F;EM|NZdcI5=CG-N#9ZZUu?-Nsl4Ohj*!!*T|#S?I&AR{A_*I4Y0ru0+%$aDi8{`u1n z7>ik4VXRT45$`WYNJaozp4D!V@npFJgUkgl%VU9l&Fcl)JR#cE5%%=C`CH4s!ZtOk zJDb-AhM;nj^yAnG{+M+Da!DO~;mi8|{?0Utbqx}ymT8J?>ZHR^Vb0VG$$HwHvzyz^ zk9D|j|Ks;ecZ@GWZ4oH6fa5kyJ33jrbUajQt>*W1+9rYY8-SLqez*4BS7Wv?k~Aha zJ43iBen4#hC+dj8ZB>}=Sow^_e+uGG6w9XYLrfSsb1FJ6-N*c|(JJ~J8YX1(7x7eghpAlce4b=ZHQ)!oXdCN*f-!5S$ibdImYU42_j*n<_-;tA#8Z<%Tdd6GPe#jX}1mINo)dh;(?W zAZs{_#RS-*9dKsYn{T_&jrKev$Q#Z9>q1v6b{mO8g-DnJvXpYE!>|YZCs3)o{{llj zIhd;DzP@5((2GPMscuoSu_84t7u``hFK?|f?Ia~DD>^v%U1F~LEP=?P6!~46v)C{= zpU-P&Fb2cg-X61n!b2IC+2AkQ>*hn)cvG`uac(7g}2|2BoYk(;(24hlP4w) z4kEOSDpqrf3SE8C=x6!vE7^(OFE}7Jri*I|gp-HNFM1y`KDwU!*w1-v)qg157MG$b zfOH_6g`yKV{E)USb2Gd1$g-e4Oz1Z$(?WSvw^G3Yw@&y^X*CGCpJ-p zYO%1WXlU|#@+HI-@llXDrFD}qqSX}R1qTT`pY9B}Ma&7Yshm2jo zax#xjnzF;tdY+;!o?A}y2G?(Pc@-+CO7-WFXZiSQQ;14U;?TP2U{hrc0vm>FgSQ50 z$qrwZyzg`3j?Q~hAJWb|D%3p%^DA!~fsOTsfA}ZC#!OA16RFm!R`==eqA{!KT_d`` zUlANPOF=xN;`c_9_TI%*;3VDk{)!k7IvYrkvm*75#BDNCkgvIYg$|LwQhLWp{w!R1?KQny%jqTuJiLbaZ<2W3Z%)`zkv!Bz`4VN z6W&RM1V)7Kfas9_fpSe#Wh~6lehI%;A(R^5k4_i1_a!hum__cII>H5er%oq&iOTAn%zj_~b7^gnBH z=L_!5M+{BoQHfyPZ8f>zCJh4LRS-R@a2Edz-5gEpJNZ;bnlb!~#SA7m*_EkZYpuZ} zcPq$HUl-Pkm*BL#lI2fl?!qBu>t7NGn%)ENefo}^+vOwhY2E1h5r9srMK(PxfD+It{-CR3lUA-r1_j2c48({7^EyyzKrkRGv7q0*^{w~qq_x{mk|Z9?l1cs zEY^zsN8r3R+{f%A`)@CRL~Se9^!{3;jR^(O{vW_pyqfBl7U|1?MDgH1 zZg16|EP%knQbj00Bnh?QuoLz5_#w$w&IS-a)m>``(olJq|dfIsGvEV0R&;v$TUl zu`f#Hf!d=$4c_Rv<+pLaDIh$rfk}TM#NdFoh3%n`rxvi$@D4HpPTw0LpF_Ajb^gZ| zIbw16&&PjIwoqv{Mw+r@?$2xNBBDF^^nqT>1iKv-8^&7T@!>}?+mJl9PfrI1aK)|L zaPfDu0Pp4x4SUoJZ%Js+Fzl4r8zOCiW=IgkZJKW4$YxCqc4R|dgQxj-Dr1bVOFv2k zL-vZ$E|C}i{YJNp|E^b70i%HV6~Py*qD^gCRYUiC9?={v_t1KZlBKE4m?dd&OBoe4vnJ8=n9Ch>$qF7ML%RIY83`E(nwejQ{6kH0e>FB>m9fV~TOXW{X-tQ&nt-)5$2&0D9?jtixlZqR7TZlm?N zqtOKT$6d4DT}{9Jvm+QH*NFm`adq;+!EMC5g`;~ndzkU(Qv__V zOjkc70T~0To(i1pq8&I(o1(n5`P+*6^keTyoeTij67G=oH8BH}*(zY9*8Vf!%qcT`pnTc9<3{7o^<9_ybbKJ$i9Ty?h8k>4ZS7 zjqFnue3lew{y?5G*{SG$=!aH|@pue&c;CVK{YYE*}}&Aw5Nh0_u}l!K>K4VTNVfV4f|SG z5>XtBSKj`mx(|imFHg)&1OBnnCCW)N9RmV@(g#weD|S-XenNF1=~16{UnNju+!EFg zCU&c?u?7*Unhn63Uwa02i{;u`9}oNGqEOh0Q(`MY!bQ)B(~Ssu4+HU+@c()j-w+Tw zGW@8YXC7+4NO3eNuCe*^{g0DpF}F9x4!D{uB}X4B$)M1N>#4Yf4l_XlXE&om4j`V1 z(IM|%vAYEG3EZq;zUJ~?T&)CXf984rZKV9W6RA)h0cto(=xS1$>1qmkjV>=dUE>)U z_x^Blhr^O>F5l%aH!Q1#IyANd#68!ws})+(?n+n$dGS;*0?X}NNYi>lB>Fl1oJW)Pe6^{SCwMqV0>wYV~#DA*5cI0KG3$n)}UFlP8?0NE%VWb{- z-$WL0D;Ri-9qCCau?TK>;*Q{RlUdxr)2eqCbL?vNvEflwGRp;*m(un`{!2S-HE6oMCqK#)Kj3IL_zU^}5%rDX zc?R3sQJc4EY#WX3q_OP=jcvQJZQE&Vr?G7|wv7hglfBP5-<6+DC(q2RS-kJHuw;yp zYWZ7Gq>7{Z`eLu}DU6JnQWbuzM*vC1-Z_O(AaMx?v)q*>4%mYqX7z6PG$q~79mRp< z_%cBhZ2_S<@|H8nZL<1;qPY7q(*BBc4q*0c1-yu+=ZD?U8?PaL_nDZnZpg=Ak%P$I z{@OvuGo;^I=?BIg=mk_23kF*wPZ^uCmPDHb!kefY^_6<{UcTQ@je!WrSTxS;Vh0Oq zYkrb$kq!pv57)8@h^2TNT z0rt&L-d)z1UESiAixb;iKesg7XD{AZ*O`t$U#qn`=+QP(A$W20Pd|X7urv7&kpdPb z^c6n8AgAU6s=qW@@Awc(njk)a-@9=2LZN~v9I^O zFw{_vvcg7C)k6ky&8?x2MEF+>+^(Oz?)sCg*aD2%tMJJ=H5Hlx^^uZc^;BE2Kphkv zQ$||Jqlv>#m8E`byGBB=)o+`^P_cBC?wgY*1d{%U^uMLMr!1hJfhYuul>6TMO>2k z(#*Fv7kNM5IFK92T66jF3~jS4rCk+zv!}`|E!kos;CW*x^@{#C9l5Gz6SqC*j8EJ9 zHy%weYA=tG1Q8D#RG4wE;ZZrYHHoY4HN>m4u@cxpL1p(lPoZxiUQ&QC*cO&Rm)*>F zZGG>~YN`GY*e>meY`BQCBukI~Yi^9hn(cNW5zvd*X3gOLt zZc+Ri+Q+e5H11`LS@7ABnl&bc6m)ur;f?UXlupKQh&JW;se1{-o7 zb|&+0;#SoBqF45RsU1*fq4axyeHDD~ldp1nFShbD00I!*J!36Yzu4!me*1KL>__=B z3qxr|vI%pI{N%B^&r75LYQ}*0D3JbBg;4D!9!&{4u1{wLI8_S=CW;<+U2%)KNk07& z7O}(yJedvh@HjS7Af@`3?e&_y4n3x$%}>(h+1v1@J2~cXdrnr{%95#5*3P=<;#1qi z3idNsQXwEwXN`y$h`jzu^xlK-RPfph7fi(ia47x7#yX4wlx(pZpxXyjX~Ebb zKwm_nkg`xoh_KVUMe4v|N`>;J3j9_bhl&@rbje?Wx*OFLxeK_`GkJNKFvPK$>m8;i zGa>Ol6Q+(wg2xtzw_D^2*Hd6<01RE8dbj*&aT1#`O=fA%R=D}XSS+evM|3^JRwO50 zHNh&nrku~JO50N35xb%BF>z>M-ep@?laY-TzdP$beroh~=!;a(UhFIbJqHHS%$ACK zo>e$JgQG@qWW<}RWLK*d^H#dcZ1+iNUe%@fGC5C--6yZqb}&h3D#9u3i-qH<<$R&! zBDK?w%E~*@4damzI7Mni+#FQ2K0}iVrOp;QPpi55gX72|=6_X35k^yq7-wx>$b5Q4 z6pEa<{z&l>7-Iz-nHpn0bgpl@(e)X-&~1~8@0rF|;vQIDzfPS>NMYKUufCI(5Vymi zYZQ;S!nbQTVr9?0_{jQy&WA*)AvK2B7d9lB=llGo7&u=1qY5Gvn)w^VZKb6ZPY}Rh zHBh*9)xu(jds93x{F%LO1ASJwV}sa;UmM5urtktK+Eoey$~jbPFAO$9IfAnx(AOKH z0>H%k%u9<11c|#wqCAm}z{Sx{5p6NfebI=1vRDH~K|D&W=NI+c)+6U7pF_f#f)iBM zR!Ac%ZEkp>G#q27jA+2EJusM%yCsIwaQx|7zsX!)#^>W5@x)0Noqk+HAc3rFGv@?) zFi0W3v}8hRxk-1#V@Q$l198mo9*Ic#2ls#&07mL0A>iPf6s18QgP=;vw~uROTq|Ai zyy6>i0rYQOI$<5j^QuldDu!Ea88UscwXi5ZjVc*Ef5=$pHSGj00$(^lN&(Q}U2Y#+ z#9w$Jr5Ea&J(u_yCjWF9 zXTD~au|@%aBP=50^ny@MFP;@_5kBzdT2Lv{*Y3JdL81JBXACbCUBYQO+1lHCs+!GL zjKHZvYBujeqP&mbjnwA6Ka+M_GT#{H+6WSf(KIvWg7|7Z`vj675-u$I;?z-riIcE< ze-VCzv`xVTkrfIY-DC#)IV*`S3WRcC!Rk`DUnRDs6;}|+8QEihh+7IyD%=xi;aP~K zy<()y)b%(U;Z)_tz*hht*wg?P9o31%Nkr*sS_974nTTYo27GAi$(ZdQOmJ>Oe$v|B zobJ*}Dog93-lT#29N1f76)60nW?U%)ay!9DJllQpa-p2TrEma>pIcof8uDWDdEjcR zpX>0EPPD56h-!}(W_vRYpn{^n)Um>WSXOUdRsp9)ayG!wi3MGFPv7p=)exGZMtF2; zYflFr99$z__}lRM8NG_YKKlz(hS1^X_W}#;96lk&G$d z-^jeUHD=DcI7a$fp9+_m}PtjI^@{*`2xM}D0TjA>0DRm{=0Y z6CJ#gYMUgyTPjFGkH}@OgQ{;dd$a{kNl2`gbzN#dDR?U#ctE$~ZU+k7AaIWX-^^Hr z>D=;SaPIVI1EE)k~h`$8sQv|!mF1hNd(Xz4O_6!7( zaICA)nj1|r_5xvH?z}^vZ_^hRfTcQ*SAB1dC2f_-o!TtVQA(05NaI0ha>(JrBnmzIk%xbDmcbxRKUm*yQl8sk+; z{FW!hu3rwMuftoEG6e8#57|r^Xgx_G3Vzo$9gU01r%Q%r(8iv#udn6n5ln>|g`gUkZU)A^Y-Wi6%Qv`_LFg>vb@>l&AQgTk!0A9H^6z6+>^Obrdde+P zdpS^G*L9T7Q`_$G*N2)A^FbbC5yb=JD=DxqD}Rh22ClK0;v)khJX^Xi~`(Vk?2!jD!ChE0s zz&CtY3X+di#2s6#vW55!PW!0~)8&CkEHShWsR-0{o;158?~NF|DrG0Kru_1K=eOSQ z=O^3}9^EQ2pYr?N`=nE;^Yv-lx)7DaK;+jJn7`^KIA8MvH3$-;7oT(Jrx zn*v6DYlZJ?2%=r7AeIxZn$9;u(GrsW?oplJj{7@LA39GL8ZZbe;KJ5D>_~*_@l;mK zeg#y*WrCBE>GCfaW(U(~bO^g?y`3#Qu5+ry{0kEP!(gG=!Y{coh@Bs%vil%5|SqB!kNvB!>wN(g?+3y#?Yo)4%sl#Cc7osLoP+g=@I&P zYycngQUv(!=k4;FlnPOR2%OiOBj8{It*@L5N_xtEtym}!6SCnJ+699I>~h z$>{^CNei9((`=6@kY&ZT>zu|wB2;5Ps+kdxrc4w%9}K3~(SqhN{{I@%7lcSu(C0&P zW&{LGAW|K{yG9d{h??KB&Q%fsRuP;kG^4Hwk3(*)-UYCw*TG3jOVbI_do}TlM5N=t zAI7*vC-ZfocnAR1mc@0S?R5ZP)*n84q#!5xn$)Qg3FB|(n_gC9 zflms37=m%Eha~|J<`}u98HXQ5_#&|uet;1p3L~>V3$ikjyu==xiJ=lJZu~M$fvos- z06lQ@hXmliF`c~M(h2pSfWkK>TFQ{^N57EZ4_Oo<4{I~if%=veOA}2RL-Wt2nvV>; z9!P{N{q%QL;Q%tYz4i^U3#9Wq@QKhNm<(7blK*6hoAy;e@)6g)gB!i)3$p-x2p!PA zx;NkxWnf#~3=sGql?8+}n)Bbk5T~%60LLB*c)Yes+m;2;eS+H$1f_<0GPk|ee1;wx zvODjx-VuxfB$pc`YJ^%yhS}h@)Db=y#Qawyau^l;$F(+BZ4sj)rv-|{4?VHhF__>N zA1CoJP8n^A2*m}5-L7#@`|-TxNUFLWW0eiO*>7v2?AJ0Ms04T4T)8~ZL_ZJQtN~hv zpARJe14P#G+OWy2h0TohP(+7v0j~py_vYJ&hxyLAjSr6m{>-5;EL6+#c__hzHWD>n zWoFh#^e6Yg=ScpTu?-@!HF5vzsCG5^QnMZh&Od$qTlu)x8ALt3d2m$Nc5&>$~O~n-tA|VkV0&g3tp*geQiG^rIo}d_qE{Tka2+vv; z^7HG;t;-V_x&0(|6Z1THK#HW@bG|?jo**(a%jIo zxs{SOE9b~ePFz-J;5SA;bnu5i)y({14&0oZZB$A4(M;g$(RKg}cncMv<@OykV-Msd=b{X?t*A9rKu{}yBXSj^SF*Wy49%V(lppkMO zf(qK)VLP^eZ8b{}XhHE9Mt|J>piHWbOG-Uqq;bBjn$+ZQ*LS7W2htIbGzLl*II}lK z`O$=!W{$nUU0E(TjS^BO1>WFipf^z$=r$S*=>1>C_s!g?N-~We*^a|2P7Ri1^Y6#? zUp#I7%?##G@6{QR*6e~C@H7ijS30QnXnNv&KM zrX3;0SfUZUtWtRcKdjveaz*3P(zEkN1=yv~3Ca4CHbz>Wui%P>Z7!+*2LJcoenfs4 zz1(dayihRpbMf7_=3@9&oST}OEkvq@@n#AmO0QU!#r!)giIZ!f=|(;P!!53}L7V4& z{P0%+g`*4A{s~Z_f0^R(dEjB1`PS8G*A~-pZsg~FhKq|Z7>gP1v<6_MAf|n8$(}P1 z6PFOunSTwT^Z%?iC?^Ix=;nT^Wj~l13`R*L?tEfOQxU939d&338l;!xlees@-6+tFLte$Dtl9}`q5Nr$kC==Sp&q?*3!aUL&wa!POY-7+W1vbAearWjnnx67O!FXMupe|A41Aq7 z4!nR5P3!?z9i_Fcn8Ww)Rmdw)rN>5q$$D?ZgD5I_0$nrFb8M@7;-kKg-iG^39kU*m3BvDO7 z1=luG=5q?4(<3W*mP$GSmKZ~_vzua`5A=0({tCm+`S)O@<9RbPV$N$okN!E|Jvo&- z_SHn64hc6$D1zPuSaxQ05Y*7*iIvzr%hsibSY#We>=uFF0aOvjkTFo;h{5w^0SZwK!D?Ir@Ke zzxKz=sd~C>{wv>*2GB~J*|NKWp8fO8;f}h;qj1AL6qEI&r$B$7Mam1X+B9Xi7JBJH zNBM)I8v(W=F@xjmErJnY`y}An0)X zv!&Tk@5x@eU46cmp}ri#XwOVa=tmEoZ^+p9x;1tl6P*1q=#KN7NkWrA>#_)pfmdY8 zx9QW`I*Oq+bl|K%d}XN*7Y=!;V<(p@9$aVcyqDStCl=*D{sbc>3uJ5<;X=r%L6}7Y zEirRLbsKtBM4OOqzxw*$E4s^X|8>TUKAf@ZQ%z21l(9p`+b}9RqFS&aG80LhxP}V# zMas1`k~t($JoIzMT67{}*eVw+_DlZdS5J+Ouk=xEcsKd>sgA1;(@2;sML7*|UZ>9|mu_t-ML;x$~XBz#!awAaD^VgU#|Cjj_&BP$+?gyiDDB+l{kSW~jmZ!i z)=Gu~XF>~*p2@ic^DgzPXchvG@!p9Cp*k&YRTcAzL{Oprk@|znI3l0j=L zR3~GtDSH3qZ=}CM$Ul$1P9lr?F9*zIaS8YVW?MK9?n5ZLKpbCvv8}#leS1c>8(~;W z<3UgedrvTMQYCog1pa;MLs|dwbc#t&6E_6fU%)pcgV;}jAbKr^^T`gwI#R97Lp*{GmJoQYE2n3OfP%$JmcGKHkkQS1ZKO0&`Xm&95~zZ-ic^oS*D_ zwQ=|$|H%A-otFIm%5Cn3$VuToQBxEpn6hg0Ukz)E4*b{5!1{FF;?&pY3cvF49v$e5Op5B z0W|tfE2=L~w}X$JPX&Z5$v|Lpdr8w*){`4El(NZTJHp0_+nxU@TMtMO0YNNT0&)vv z_J9mC#9x1~<(twp)KbDrqA`#CM6vBBKp1XcIB{*Eh{@Vt3O9VSehd37NpLaOgoGpT+#;RVoJDx#|kgcw?WVbyj{(DZY z=bB%(FOy(z85EP&m+bWK()@^A3(XtJT26aN_19#U;&}%K5n!*w$!}hArzGBhtTI05 zQx;)d!KA2)`G0L$*DNB#|5RVHT@m61nJz6Sr~*bHd8{zkbVR#8-u4mMtR%W<$5BK> z_}i2S-8uPB=teetkvJ}xc){7_!eg?V@m^ghPbA-$D44bEck-du_mO69MyhY!7$F^0&xMu_28UAriYAU(mP{OeP3 zW9b4X1qug*k@f5WPiyQBy7W zO3nf3OpN*;^VCf2Gx%+BRrvEt(M5M-QGU$Rlb+Wc2T`Bro6*rE|0I^Fv`JjmM1)!O z+mC(y91|qxR|%2qaBuG$M{DoT?okbonycC1gS#%qo&Q>Ijk_$r-&_Rf=rm=veGld$ zk5B!3!2GA^A?MHA6tClj?xN3QHgnP2-xh~|%*v+|R=sI&utAxhyjLDRP$Feg?AuL8 zY9Y-MrP*5LSH9JCgDEtR|6V=34{dmV{B7wTFob)H(n9dBAbE2U?Lr6i$BJJP&YD!Z zad0OzkVLAvk62wLfRMl1PViDcMFqUk)?a}k{#K%v)+{-TrUM1?Sm>goIXuy& z8L93_VRrFPHnkvS_g)PXX(@ey@Z8%$gFC8o zY77o>|MoX5<(X_YVcNxqv@3-~d_44^)xkPLWIkzxWPNK=37Vg-dkr{O5>9xXW`dZB+8a3ASbrCWa zp@*(&o%HQ>1{2Hg`B0Aeu2=)%S(9P%JKZ%*1Og{>Q71fRahvpGkv6@Tn^^>|`mfty zjklt|KD}0=M3J)_XhkugmwZ%=%3wNw^?HRVqn>8OQcNYCfTHTv0Gs1mQwp~A$-RSv z;QnbQY4}8K2J)WsAH@=5tm8x#avH@4I_sj$3yV0mdA%H)6KUv#Xbv(K88pu)CkWf! zFD@T7lyj+$&l_yNr=~2>Ptq5jo-mcXWgXKlRWk9P!Izpfj)MysnRcPFAGY7Q4G-Hy zA@3Wp83k#(jTo5%9(?VBx5l2!PtLq~5uI5E)dq&?mu^5I*Z9X};Jl)BT`3C_PZ;B4 z_vDaXri?utT`3TI0e>KXZr#6{yAM{&+5jceTa^!8meFy;mXvPubFjchjdMmQ9DychPS3GKY} zFJ}dpL%Z9ahB)&{!XdV<+WpPQye&wHZ~orci+!c==evS0#lUYmLgBgWd_0q9rP8Bp z#8OhPW_lUlcbvlGc%G@jeczqCl8aX;1Ha$ZTo3Tl2slsiko?g|kMptkp6V7pxdhkz z*$1b(lnc^VVzuvq0VVZ=Ko<`4>ayjKHbpd7N5_p_) zPJ3PVBmBc48;FB~+N1yLTm;&`iQ3VXP{(0mdvUQ2c^;W3J0G3&;w60O<@E`>U8i&~ z?;BPYPO+fhv0y}~>$E$^`aB;|oYYG-lS0&i{ha)*-pabX4PrCm7cV-oz)=JGIlMye z{Hu1A++b_4>ll2(?lekpOf<)>+;Dio2ZCAMp8#2^d`lvFsnHhVB^7~%Cf!|0Q&`6{f<0ye0OS4=IsTp`gz5ZB| z!nb-)lqZ~Z_#v3D-<2rgF)(g}%fp=9d487r+ksJQ*DLx#&!YXprvu#-hr0)oUF6wP z;!CR$|3-+QW-)md3J!l8f{eW&W3+$yF0@=sX6q8J5Cd^c9r-WrJ3O~AeirR{{|Xo6 zEo20x0vXZ?Q6U18T+(rIn8($xI`FUghOQh+^As)Xi_h=N9tfA;s<=1anLA1z!UDJm z`ER2bJ22PUPzFn#*_I9K(i=VAJs!^A*j-%eJmO_qYT`N0?FQNUmHoR>XSpGuN**ew zP2F22-Nbs9kO<9;Sx9d2`D&-eJVyTU9<*OPy!=kj)~T5#lr>}jMiuCHv1?lBbSJ_@ z-#mVIJ~H+LjgM~XC&`WA{Q6$K_+-0maZq;B z3KBGhfF*(K;!8ho=#}Tp{5Rj!sL1KV#lbP@(Jn@Kmkw@90ICM!PB!`>>6bl> z@R*peJKL6neM5Wg_B3y*8G{$8+nPQbotyrKIx~6}e(ZRa z>5AXP*)cOpu2>kOZ2pQwFQAovhHqU|f<}T$HT|YMnMa@d*P^k_^^YFHpZ4pd1nAeJ z3>D!L$80?8N}S2@v0W%TnT2~kRe=yFUqpJGT|Xo~Yvgm?N0AI$8S z(=fI^*MP7FKBr1dx!~ULJM{?3t<@%LIea)}k8ykHpHI4U0NR7L^@p92k5)S8J!0eb^WUO?&_qUO_)f*c*bK zG3!m#(1}FPrOX5QM66B(74&C{=#DqLQCd#j4t zjx8U}{9$3i^?ndSq=v_s)Ork$GoIWC|4}ap@Xe*uA^Ql;m{MW4Mi2vfj-BPr%tSdB zK+%?&*UURM>0+*oZ6Wes219W^8GYG;dz`*ArHF^%LSnX2npGI4yMMcF=_`r!BBWAF zM8f0+frj4_vp&-~E;7-wB{K#Ir^^4;eYV1<=T6hgV0t1(SxYWDTD&s9EysV7_4frN z+28k=b_KPOK`@fmFCzSug*#0yR!@ABARM23FolN-KMa7%5UC>teWroWoYQ5}Y>@CrQlfuvMfi z6wuWq;)aeimb^GoYM;xwF=IPFi8)T0Nd$wsKlnvsK~eF}F2CnQHo*F6*bS%Dooq4@ zGX;aM)soz%{`9$Ee*0hSelA~xro_2<0tsOTVziUimatljp#u*m6;7ZaB`5jHI(#0h zXsXtICDK;J{VGf_D!WSG){BnFvzI}0)HNB|MrSr?$Z$pu3|eXZwDwB&75q)PA>7=8 z*#K68Mk;G;q@WZPXhmDds3qmkk>V`2-9YSB0E#8yDPAlr9X_WR8xU`&_a3CF#qLn@ zmLJh2EufvQJzmuj-+OMNgy^Z%Drsw=io9Jzof(md6l>9~+>=TTABq&mLet37l&Jz` z5%Nrr6Ek(ov=7CG(q}TrJ^D0}y1`6I74DsW33PQ^l1ETK z*AXS8K}007b=P8(c*ZOXeGE^iacX4i^w^KC=Wc!K@2g^DC3g`fwFP~(-4hrBJ%$2; z@CsG^=Xkq*ZHr~+wpn7KU&|rusu23L>$EnmC_1^_wF*HTKOlEVCI|}xt`Yw2_1a@@ zb>%U=y)6|#ezazyY;Hv(6+eA)V1VRhn-j7}ux`>zoK5o!tb+8uvjY`k{bL;s-%Ak64F@_xPiks0C& z1ig(0QZuHy9hfO<)+HXt-V;h$x?_)B2^hN2NQlcKL?z zmk{O7^tR7>;dJnq9;*`$4aL6iG+trzl(U8&!#HMN|uRt>)yBrBuz4 z7ZELuTx_on)N@U25UD*v@-49`9%B^>kg9aXgXn=3biIB5w|D0`qdEe4bmMA2M$E>7 zyVrmG(~}<1ap`rUFc_p5Sm0Q`lZc4HHSU_w-oICdM_E0@=Y*&CYQ-n@uGVjtc)Zx3 z%&v(Qjg}0d455OM0CftFY$-q-C|S6$GV*sp5x!9;ra%gzX!2F7>q-D1tes;qz(M zL}L7Qk(iMzUZh>l;p27w^#1-hSSXBOe?_zjE?h1VtERQfDK|%jm}p+)#v z{%ya1K`WFmwlw3CHFJSe00!8PYmBhhCQBeNx4^>smhs}tI<_*F=sIVlk**(lw0@bi zu1WH8KEj)DSrn)5gPz&Hv_a{l;j|tW`I!IW4b^wkJTNm-m$*u5=2f>Y97mV7A^k@F zP&^*nAh6i&{3~Oa)6V>@RGeZkHGy5V>*HF$h|r2R?%;w+ZC0h$ofPHQp00L&WHM!@ z);!JlOHUwh^E3FWnd83feB!3$`t&EuQdd^X)IUi|QPC#5+;Q_^>mm`o$-iQpf>co5 z#^Qi4>`zZV*4L>(>HZ3S#%I@#KeOK!FGO@X9%6?`Rn4sSoAxwa3yl$uo;kGB-ynzg zU7M4ui6ht}Vrr>8sSHEf(SI!E#(j!EpdD2bZv*XW$IzQj@!|01UR!S1pt_ zFqek6OB-6Hv$+Q&x;m+4H_v=29}}&W9i9xo8wpFJDcx7Bmts9DP3$gp0+ zC%VDZR$M--z4n?Vib|oolHNBb7d8$gHB68!nX!mP};q@f2hr`>EMK}mR1iip%u56KsehD{!+2Ws76V6$KJi}o8 zT^|uXmf*J^X0gk}0+n{!Q?~3c`o#@NGHH-*L-pemGDnie*;1U62{YQZy0 zR>{;dU}wd82Bo{6IeU~ly0%HE4&9~PH2v@|DPrnKu5 z!IJ-~&sl$zWU+1x0+r^>pBGfl3%mWIR)HI5X=>W3PA~XXaM>Ds7RBpodhbZ=Rs3y7 zfstp@Xd_k$9EMdpF&1P1dn6&TTR;&Xk1nSu4TUXp_z(eb>#QiFj-w2j+}3ZygZ*v& zmZt3`N3sa#mVN~&aQS+yE3VKLN)toYngz{*i;3fMw^bylvf5wIsH|v?GPG94=#>*o zED9DBL08O#DsI7l(Yuc2qzp z3O6~*MHnt^O_~D=aiSuPW|hIiZIkbw{~g{;t0u9S7>}hO6|oQ?dxUxaYxj(I?^}>s zDIp&3x;C0>au%BhgbJ^Lnacqpp3cy2kDc_yBsu&3sbpHx>lm3k+ zS7q~#%GP!6$Is8l9&sG=s$+p!>V3u1Cew5JVGfF9Xw6!p7!W-y1?z@en@=#ZIvgSa zuS$~o(MpI)5*ZT#0#;(Bh@HLpb_A5R?sK;sa4ecToQvP16mPWh;*6_pj}3uUNLgLK zg-MeO`92?>ILyUKAf<`8&W1T^Ef%ws*EQOepHS_PFb_wH$96!7J!Vxe;bt^z4gSp! z4s|#+l${~E&MzZFKJvI4-ZKWdw!=sqD=uet$1Y&a)kR>D-J~+>(M%(8Eoa#$&=3$U zSJ^PvoE&luO^r^)t&Dyvx}^hgIV<0?zh17FidPXsCuVXT$~ zY5GoPtIo$&q5n;4?JbpdL@ZkA>m3sv?G?vK?B>|rxh6Vt5_8V6BpR$+V6l5qN)=-u z5m@0mYT5_J2KrP-ms_3d-}o9Vr8icS8sY5dSLLa2?o#Z^6e;5NNk@r)w@Mob&2o~? zXwD#;4GUp{w*hgcN=KEyvMGvjn-3L)Y%Q9eZ0i0KX=KaXlow0g6~3w3$<{TSAx-6o znnUySw_DAmgU>26eBY`Vi*OBoG8-f_EAZsGw8^WW!=uoos4m+RkSr=UI*PCpK5Ten zrCNlyfYRXdSn}K?#Z$ScW;1|vV{9lv?LE*%S=fZtwbh@*wW8B=`L{!pQJ3}@ISwb`$DzW$#Jx1@o`jGd<&ammmh4PT4)k&{ zsirYwqHO)~$2S276Bhy=;m5i*C5pd5Az{qKT93iM+j;lK({-89bJnDS3kpR8yfv`B zGMf;e^@_dOqS8}#-flnjvQ%z68m>r7AvbP1tgV`kGh0fG39qh|`o&a47ZpW|Q6pPW zN~Y-j+~ijM&gh!c0Sx(GQJx}vG)a2@+1{N7g@@)(=_u8!Of9^Dt;jw$j_TbqF;WPU zIO+Ss*_9<%nfuQake<(uE(^5qp>JzQWXLZC1NgO6UPA9 z=N;ALTc7axZ;!@}Nj*bdJU=?L=~-#X7cTzF`8^pe7@rYpFR}{CV{!JLI%7YTSQ8bV zS6z118lf7K=OsAQM`nD%?Go=7c+nC;!Ev@S((WTrPjQ#FSB)RtL_%~YUqdC2HfxPd@8XczL+{+{r}EYx%UXz2ltgWWkW!;PF!+D1aN1>1)tsPtAkMD?&OR32o^&>nbv$BSEPehND zChpY-hhci^)n}m-xvbL7hyK0q zv>Af4*%gzf8V8OD({Sd<{$~1$Nfy^Fad4nhQr0mOx0ZCsB4-|bbX2WV*t|R0&GgE# zKCMeU#h=Hrd zf?PPCtxNM)N2CbCI&N_v4$iwulJJ%w8ep(#BzQco%#0_z66Wg$M}MF5gHt!5C_;(C zrlMXEJ=A9&ytiGN{HCFODcF3QG%C5m!s13WzXT=9CP@Z4s;{@+=*A3FJ6W~29|j4H{|=Ys&d=sDW08YbR>jRd1Ts+FrgFp%sn#j=hSq-oni_I$oW&;rzh=$9*o& z?PuS7gBpbImlMhF>ioy+&Py3<^71kcs~6oxv7KaZ%2XhIL1E)EgfPAb|Jq!RGn zHF6TmdeUqCr>1YIS4K&4^!)irD(fV_%qP{@uAYmU+`jFo7m;dV9yOt;?qK9LG%nB- zX+1RYw77$ZGIlqlJ9^~KZ09bYlgXA5@(E&1$y@4us^m$DA=<=9MQzc@v}R`u{;F3+ z9?{ru;!CG$*}ibg_@`t^ye(f-(IR{)hB~e|#!8x4!-`PDfb=JZTn$}1=yNkCnz$Xj z3RNL0gL6`D7{vcmULMU)G9R|QR#E$ zHSa-T*w(3C!Xy)722hCDV@)`#<=>~z(MGRXb~SsxWD3-#NL& zVH02}8@B$`_EI%IIOC!SN1lH%kIOpb|9lU3e7H9t1_L2P9Ph{Cta+x)>TF+_8+csg z%;oNm=oTaLEsKA2hSr?A__k1aHbm*DC*N^Lp(Pf#PDNYUybzV1sT-#^;Xaf!4Fx*j z4`Cs8Lz=07)?72D{Vd9`6kY24|6u{72s!B#<0^-cC&0To3c{ZSAq$UDp?cCap{O<- zFL@5++Iw6E-hDYT&BS-&sNwLzksPkq!#wN?e?<=_$&$?wn)G4ugl#Da#S9A_P%n4> zgUcFvdgw{2UNo8M{nOmucNceF`WSI^`e?AHYd0e7>y)1G#} zfZ%cuZ8n4n*7hAP58-KMOK8)b>8bGaU?^Ee6auD`FdiDaxNh(n!Sg1ItN%-H4RPfn_$xga$&mM<_o(SeUUf;%|Xqu09MA;5}N-F zKZ(|n4IEfA!+EU-0qgdwS@W`h*5agFd9|aG=dZ7`&Pexh$%zWB=Air=SL>C3;!Zv`@9}gR za@E8>PmRT`ozNm(21~oIZQA;aLQ;JS@quEaD4Dm-KlRy{llQrO znt?3~e9-A8r1Ol}6ZB05G50303g&<~e%LlEvpX7ai~R>J8CZd20A~HJ1@PvZNaK5s z_A7WPI2GF>+qV@RgQny2WH}C47AXuWG<%v%Ev6_SJlk4Er;z8iuDaGr`^9Et^v zQJ1(k?;shxV8(_|H*(8zk^geSQmYCmjOl3aoccDg`;#ExXTc!-nmE=zJcVM8L555_ z!Ho_msB1yG&+yyFXE58$;*`%|;wY}&$|43bCG6YXXY{CsGiRRzuRlXm&^PyO9gA*2 zV?_Bh;lnT;T|Z|i_jfD9Gh$s*CgPwjCt4dZFB{ihZd{xd4PG)X2PVcX-kVab1LKah zQ^tkr)M{+)qcX%;`QtZsu4lGxC7)(d1dqngd`Ay93*#>jf68ZolH4DMPizOVT}}Py zS5)K>9MuJKKgW8lSOllBiA(s4qb<=)>3wPf)%}LbNB;hZXxUO-1a^xZg0i)XdpT{* zvE>7O(7gnONYp8^3bZ(27s$lhPP|+}mp|x2P!$Tu{(BCd*65WE#CHtScyEob#PRrt z$KVb45!f4lYgS?en?!J)DZ=4#GPu5m8K%UYts*R91Y^Nx1xFAMg$Mdte+tH1ks&Pq z2PYcB9u%D5-8@_{zGEa7AFf1>@F`aETxvFl;9E%VpO;;Hv2Pz&sUnm4V%`hySn44$ z`5OV~bA?FWZ9c7JXALttxZc0QxikG&`~oYW)8>G@kRyH%K2-cO>BO$Q5TskqDb33f zP^`io==U!~dUNBYQHMr|_HX>W~9R3JR`SPFO`m#Z5u?wK#EgWkO3lymoqnBHC{10_;B%q7QWX47T{zSk{b zU*J`*4tadjqU;?Y*R5L(KVvi?qz3$Y!2j_D-oUu()AijB)cyG`S6=~rPXNKR8D&RE z*RqfP+b4_sao&T$3XW#-S-N)Lsdrv7n^M9$Z&J9hsyV}U9~buI}}b2!9#Bbg1&SLpIBJc+{*A@op+QNoLV9GSL5>%-Qpb8}{CSC{2yQ z|8h^an|UF^vM?kqoKY#Z^f2L&YqY0210k_5_ zpR)CYKY&EW4N21JGrBTsAv_=Fnwv^Dl0#3c!dD-lP1SKbk=Fk9-)t+Jpl1 ztd}sW5c1!BHaMKp0IAak|LonX>mM7}8YBs)7&T<#XC`7|vb1qVDpjnelaXoc=9^xP zu_E^%i}&V$rM~dVbFF6U_O|pxd+1p=*j$_xNCn?N@F_((rm$8LZPeK3?i!qiEVc=Q)%FNk8A%R;mm z0vy6A|2ZIO10I_sgEDX~^zxC^)e5qCHg^bY{%5rzQo-`(qKz*n)_Er6&DY#KROk6# zwIqQ!crI!ApPw%9{kW5Qe+yn-EFHfW0HqUe*gfN$7OCeXGE&o+|e@dClFKe#V} zgSwHDFZPc^?fQg4=U)SQGym>cjYJ%-XGDj~17bCI)h9Y#|9plOv-UYT;c}c??*{t+ zG4+*QZE#)FS8;cD4est*+}*9gT?#>q7J@qjcXxMp3dJ3YyE}!pZ|)DzTJI0YTFJ?g znLV@j%!v{7nIQf9!w;MdiDVf1{!$=B-Y0^(1H!z7zg=SGtQrK~D*||M3d&)hbAqD* zcFzN_(-y}>5S6LqNy}}u;9(ML0 z2$i5F^c`h)#Bxm!6E%8(YH0>VVP&Y zXC3id58S_dB;K^4>C)Q)n9LmXc>Xmvgkx1iM`F=#%4opgkZ4p)NDW=oYmvS*k!lQ7 z;I`w2;l%p}#WgB`pTYhy0S?#Bl!NwcqPj5uUf?z2B0}L#Ps1y8Kz4x3?LFF*v)qPe zifah6?d;GRq=5!IXwi|UlLmDs5H|jF&s=|C^X47H$vhXnizA9GBC=x{ukK&3O0lGovF+97S1dBpNvxbC~{Aih?WA=kFGUyoaGyi|OC?BXjA6J3 zIdQ2PgA$K%*sBp*-bFsOJRdXXetT%A?xxJ1tp6F_z7w`|)*$+efpzYbN)MG(K+2ez z?(4v_M?R2Cj9hOf0!aGdA*Rxgnw}8i19hVbzpg78aFk?p-p&XW5NhII&K-m^LU+DP zZPcfWU^e5u3dFvCf@B#ob_3{z){=PS@*O{hiURn+Tk8aSr@L28pDZ#6OU~%c|kn5<; z;JGNsQ$)oOIc9M$%x5nXi{Ui}%|9}1@yE_oKC$yF`se{l5eTyj* z1EEh|)cmALlZQxaaQ9e<&?c#gLu+rB3)u|f8S;cf4Gjy~kjOFI*2~R}&x8BCMSK|S zfeX@?BRWg9S6*`ToSg&Hjk&oh9TJf_D(LKyh!Jw&-@h|4!}>n|V}@Rm5+C2I+a!Ps zzqpLL_ki$TMsS|tJ**RoDBq0bzuk1#_d)N)2q38C02A^kyeo|^OE;Klr_oVR_sJ+2 z`E0jsXjI9L8=5MhG7(|Nx3nVFj_Umlrb@cQRa7T!NW^xp@?FyT8In+fgqXu@r#aN3 z!s#R zvkcQye-+2^cbv1k{vJ!qdG6WilCdt9Gw}(C|B3Bq~2nCfyj)35|vly>CB;pwN zwn-7pcA?zjGPJv|)$Ct(utKhkB4AX^G$w{2Jfje&7}2%LWupm7LEr)syP%+G$4+5Y zV#>8eA8vlD4-=zJ%DaU_TgQoes~ria-{Rzz@QO)1hH~B2d^M1gZVh4U(k*4uB_kt0 zZQZwfb}|?25X7gbo|=PTJMchnF31TNDg$WO)mXuuj9vF*cd8qQq)cp$LI=QY2t8_& z3i$w&^Qy*nj->M~BrUIx2Uzqg9W=S$3Po*Z!JoQwe@}}MaTh5lp>4Zs0a9R%6~cPY z9TFmOb6wDwGs(*ViYJt?sC*Ez%Rj%=R;PjY-dU=@i2u&LDYe}Mg>hI*$OoxBHEb7* zqUmQ3?A?D>olpufkU52oL&OQ*gWB0RbPPp#*Lz1C@bKiAB?x!L5?=uAe16zSq7bjH zN+BKfxS5G1_(rdcR*&B;kfP6!5(dd-u+4cD8Dpyw4KD2@ww6+EjP|#_0SF17ay~m9 zi%d-M^2i?B4Bf1X?T6r(i4rmB+Rq+?O2-DFwSbf&?c0k z+b9Sf!boc6z?*wx4j%jW!TefbgB3&0jh-L1EM9UW-2bk5Y0#A_^GY`(HY%hDhaM^a z_f@37^-T?8{@hepWC8_6C%w@)rBc#k0h`qS0G5`9_QtkgnaPP-|0>GWxvnM{qit3} zKeSm%yf7fG3W(%A#nxfc0eZkm;Vl$)!P~lbxpj$lh~@o+a7K7p$efz=OzSAoleFUG z%EcLh!VoIq@>DP^3*yyS2qm0HGczRB`ZVu@&@-TFNK^Gb$V~1%(mliR{M%La_$S-)azv6epB}R_6nps+MyRDa9M*U&bRCh3-wBM zSD!{0lGa-vM`|8s!OZVfy3jL?^0xbUkpR@X1iRqsv?}e9D=LS|l9P!ckYl@@&_$6I z;S9M%WD%S;z3n%k_$y&&gG%tBA6t#>+@gR6O{|+64KifZyUm-($5fHWjD>0+jnGGR*HUb`kcH*1-zn{eb{aMqkox&}7hmE45+Da+n=;*w`WNfB#QvV`6scVB#%d&U^ zaxxE|KUYrvBoF)dfc^0#U@4dUZvnFVV`|PQZSru=4RzJ%Z=#}m@J0ingBVtA#1Gbv zW-R9VU`0fp`#{5@-&0RRNq>Jx{T6L@7HfFH%CQUSU{p{H?@XauCaPoH0hvIzTfPvk z?7fyM>IG)5we2wR6fN^vl*@Rf`>tl!UAzU2uXBPgKBJftuNrydw)^4JVFRx;W@VG2+=l*0^-4VcjT&g&1o2 zVJ}m=n+ei|h!lQjGqG>-owQg7Dgy*@RhuhGGduJeOMA1EQQm^4zMaL_knuanAYgK z^MfN~3NfF`;nj2{jR1mGyY270*L<7|u)I}2TRsg+QG;qR1R!`1_MZOkpv2@zqR-L$ zyW2Za_Ui|C9+horgwJF)@~iGsxKoWpKR~IgwsAyU?K}k`C|dR{a>%9q(Pc@n4t)j=n!Kzw=%S6vM>~u8Y3jn#od{i zKC)rV^x#Ff8|TP$L6F0zRPvBt`Jsr%GH4CHgeqpAFbQadGR|7XTiX-cT6hPHy9W{x z6K2UERh`+Y4bc3s-jCs~PzhjDAx==|Cz__cowLMz6hBO-?N3L31|rA~%zJBwf+xY0 z5(r~@pex1_Ku9;LAMfq05~tT-Ot-~YKtpbrkHa2IOh6eUje@UBXaZSW3-=aqVgLEw zuQsK(mR-q8=R-Fh;{Zz)U5;c$fTZ5wAnt0rr|DhLb>-$j>z>}pZ`zp}+_Ox^)PwTK zPYXX2A)4NpSkDeoR5CfNt=hhSheG@I?TDH4&xEB(mt(Sbf?I2s6kc*)`}vce)kygW zXGRD{ld;M%s;`cZ@YiH-?nN@fWOT{mOojOEfihnnP7j47yuyWL>(~rGRD*-QUdA5Jh)yADUP9F3rQXPu{FMzA_oEr9m)-{)DNr>Wa?8fzhB0#vPURR_6{Lo z_Pk(RdJO#Q!W7NDz3{QTw*plF?UD$jk)NTs15?6g9hZv5t|El0eI6{p>&PB0=ypQ_K9v2u#}X9&R#vBB*cYH zkMGW~+-|>1Eq?kL_@C#>!1h5$=j|XSS*Y$;D5A-qDQPgruU9Dc^V(GL>oHR^wcpKe zcd~TdD$gtukxSFL|NWJGk$ik19{$7YO{t8qtoU)bTVxlw@WsbNu|(TxvH7%6rRCTK zBTz$qp@-|xy3(#=PR%$b<@q~>4l($LaaMSFr!q|nM0wFYr*1GOb*Sd(E>j7LGq*lZ zcIo8k*5-&UhpiNhtQ-M6)kxq+NH z>99)q3pA^Uwv8A5$vac=aKGZVY+1fkE{2D6nISeNQ5~L$5okC_kx_1R4>0X-GEvhE zW$e!!1@q%}^kCt`YYI1P7L23cVehuc__yEqYo;k~=^oKzYl}h3*cXb$Yh6^Fzxxpp> zWX4}w5ws!^$vCv=^5>P;b38YNDvvIR0BVQ|ay+nUv(!R4C0bo;Xf00#KqEO!1a&u?c$>3MV4zmC z_6epSBS6dicT+3Afxo)(3+AQexJO6}ddbf>lDt;5oTe1ajdf}8G+^jX16P+?!ldEP z?EAd`V3oij)eZ{Krc4fgA($Yc5q!(`SAVE}FlL$&jFfT21U}GKvBhamhyMnD6r8eC z7>W}2LY4JS=rgkCW#P>4etX626){O9B5b!h&gH7g?U0=tO*_NOFTyF1Wq+yB{AdhM z*TE*v-6@+miK4=E)(dQkPeII0t%*H4RMtOJjHMPcjcZ**n4kaACla<+vD@`vNX9JQ zn3tt%~U4S~FylbWMRd~L2MJY5;q5QdZ?o|Ws}g=YtLlg1F- z`CEWT>k9@U?{J*xZ857x}3>5ui6Fb z3laYK>ebC!fzRB823Coum|j{l0erSisZ3xn!VOVl>RGh5I=d0ws)F)z*9eWOdF6=n9CGHl_C;<=XAu+UTRMC1mx~_A^Szy9nYYzHcI3I)Ph^R z=vW%6%b0SvDQmc&bdn`1UReNOIA2f|GLksTFrYgt5r{+Ndp4)`W@cgy(?bedbG64= zOAh7cOt(W6i3f+?c{t6T4n5K$57A(m6EY^27`aiXoHn33vtmi%WkY z?CsM9ND*gE2d8sfBQ;>ndLpWlM#4G)PI6&5}h>)Tsb zS|{ewLg6q@1FW4Ml>Gi@4`=#6;-scmF>%O=D2>b>71Y9>GWl}=H+k|FkTT>wwqHI2M(VrubsHrEQNH?Av8RLQ*Hz+X3hDe<*T;ZXeAq;(8=9Y46MVYX*Y|0ZYIm=7 z_`ab1UGKw4Q!(=2J@w@*8Cv2}z%=y7yc9vNeACDgE5euMa?-{p6I&i1d6)Xp8JZH4k~qr z6WUlwa#i9O#Y#S#kraM~8-vjNAcbWn-@1{3Ezmy|yzfc?XR+IBf{NwgMHVVG#N~|L zRsY?2e@i3owJWG%Y=n-G1i&^QBTY!O=#nbFQ-pWsXFBFaAdh;iYekpD1CE7)s5i)V zb%XUTP)*qHLq)`Pul{VmbS6q~p8T>eW%AGh8};TQQVB5XS63H;VPOIw@>>Ocp>63ZcUx8P7wZVwgcTj#`G2BZ6Xqd5JMX;hdkDlr;CFZAdCqZtxf3 zITnQYgGq)yWgi~&$XV0>pZYfJXRh13akl}4Z>@MHxeX6+Et}NbB-c5g4CMsfaH_fj zM?3NhepXoAFks=eqSkTKDh9^BWjBaRC6d?^IL^W&;FDQ1Va~rTs>kR?i zpzhtU15RI>*o0^6UtFaFxSrH%m^65q8k3tp8k`Ap&i|_>zcxna8Ap?V@OD4;Xm%%W ztU)bsLrip^Wi2)AOZjSL!P13^ZaDqcw!Gi;-fox3p(A()3t<~7N&5N-?)L+<{>E(< z(#~h-PF38J4}_97(e)5NxeDVbqOknK(&Nqd?F<7x6u$(W995|sf`Z>rg_+w(u?8<>pr7TtVTV6G9*O0z z&l5B7Nt)OCH=)89P5T3d-_LL@JfbNd$lk!ug zlf~tP;lNMKIrIB`ntlDPnj;Rer)fsKN_qiVD$#=i zx&s^%;SnsB*5WOzLzHa;m-ueBBsslswhmJE!Nj;!A}|={_lm!r%@~>B{8`AlVWtEP zc(HNt-5T(?QK)5L<$p?9XS?R(6aHRE)zgzIMb62c+l!dQEfBa(Jmu|shIV* zKpdtWrQ&z90<-qb2Dr7531or$r7VqEUjpV z#SE-FwqX<_P_aqFFncdfRf8P1deQQN*q|A0!Swdx2`ddAS9|Xs-Y!0*-w@8YEySKR zAdrHnx51I&vMK_MYq29Zu{20Z8SIND+a{HQkY|XDtp>7&^(q@=C3otEOZbHf)_c8q zvD~vV;M!rx#m11lLcfKktOsDTvIjR4?uMfF@uPZEhMtl!f`ebgBSw`iq{Qw1&>e@t z_itP8_6yrIO7W#-g2eRdO^w=zQe^}o;9CRXQiNJ9T1D1~IJYAHXj$i$M_MG?96+dD zoaPieel0&vE!XQ0F}lhgX`1YPd4*H!w_^)iJGa$$89*)p=&KknVA!1FdyM?AlGk;!d?xux?zyGGJ%E7$ zoT;i?2YO!%Q5{)C9KPF&DCe?dD@3-Ko3_>(A1*Iv544B*G=bFixfTB;Wm(T)JMqUP&;6)*y~;fiex{5?gw zt}=zUWJ^ir>;vh>?Y-x=uK?Uq32iUUQlAbY@&G*6@*)b5G-;z~{sM;f>^S;0;QjBu z2;r@hk%NL|%Y6s+l*1m{r9GO*#8(x(!oTd%Q;8+%DMd|_+yEsG>${;o@{;s0Bhp?% z=xUD2Nw^dJb=zW?In^B0W|5jl`1glh)^>P=H{XwqebiR|?OD!^U?{^TSQD9?-0d1C zAb_IB{`Lp!S{J%s_?0dTufyIZ%iwAFD!;UCRf5WO&pvI6yV$My%~0rQgI}n+Far%$ zrcofrLeH6-IdYB!O1}t3!t8V923P0?iah&pEaY~Xj}u_Uh=kD_ziz)WkRq)zTKiE0XUNvECQb*@+aU%j?-hS-5G1h-t9m3%08_slu~8koGraY zm4nWrGis=^hU{l57OXVRN(k%JbFYiDhB|2)?sE$dcorO>7LbUnw>2ryo2Y0rM*Q_B zPlA9i1WtaK;%x&5%?0J?Z4@EP%DV$Wj7Bh+gkiO)W`T$*G^>GJcnP0W385+}-b_Rl zPogjeMc$`2!0V`7X48K?8GEd^j}CS$5hobKK9r$FvTlNb#6D;=6wQR^Q+p8!mSCzB zriO1EJ<#qqe-5DhVBz-dKGUzlTUp1OlX*9gz{eTu$D{qkLyAh!mT*#jCgGP^uU$=$ z8%nW5W3H|+4IEep+`Ib@o+pw>xpyp9n0v)A$9CxT5=;q7HDY?q>3bocv(=(`4xWUU zNOuO*I}aB?8xeZHzb1+Hh-%EEu%R$2!pPJUX1FzG)SU&+y{!92X+HZ#Dn66;u7Xh` zk^+K{ZsJbUABkC$t(7BZB8z$3N0WsbmzL}T|kdJ*q_|6u8lZ6<=ihg>L={giOXiI{# zbJ7sb=SnoZ&!s%{fQ(8mA?RDx<25RyP>S_7EH8f-qXJV#@cNUmUXWE{GpuGc>4oCLW zF3V}+OfJ%7VM}ddQFqJ{GkE}E$>3jZ#;KReX#v+rWhH1`cb4qs&-+%d*~=8}D+%zWx|$2JLmYPOil7{#Xr_$h*C$5WUnk*he)K;SLnQhUM1(Cg3xBQ{L?PP(hrgS0 zdXm>nz(kNTv+UtECXiT8k~fG>mQyokq92u0ee6LF zbDM`o@YIm4Ro*lKzrN8eczDJ*GkXayLBEn;xoUUak+VDBQ1?RTEKJSe4Dm*^Gvkm_ z7^$xa`{5_?{AGT#{UHY{SswOJr`6QIG_fjFtSNFOPL)-GEcQH-@7g?Dovt=Y3`gv`CsB|QdK z#c5swnOufF9o^(>VkpU|R^T{IOZ%(B%262yGrBRUu_82jNYCFr>Znps<8y~I@47Jk zc&@k=)8Fl5PDRWNufU!|Vs@SV0~(%^IT>kZMzgZ^=A{L5Zl)g5mv1nUDsI2XH8TH0 z!Q|x~7%wk01>VMn2&Du9@8{gz%7;EoG=%nmOk~yRIO1HTL^dUZ^C`PZAxy~P*<;GJ z;_6E^WCns1T^D+88;#byZ~&^Im1lGFXd>}aF{6YO*4JK{iCd(O z3#jBnN#%Ia4AN%OlKFhFeqS(FvW-1bZ=>{0VW52Ti3MwAe*r-3x@sQH00^0_>WUwQxazyB9~6CSU18XX#GD{V~Q<4Lf>{=F`;9Tb4O&%Ep=USDkl>u#%Yajs+Ga?VQ zJ~lgi4`u2AZybg;-1fDOF^e#+nP9Fmea&Th9nIdZKS38l@`S*|@ToM7^>O9&#My1z z{C_(qm;ZvM{z2N2jz=&0UlJl+*;aUZ-~GaI-Mm}=B-U?#6ChTc-{7G#V`^MN^-Z;v z>YLUFJ<#j@x&5vjl%DyX9&G&HU4wdWT5@)n_|p5=deDwjd&Q<~?0{;Oc=!+TUCE{w zYI&kY<713KL9wH0yW9Cs8NnZPIVu8M=ym?MH{`sEzyntCHsZnk!Zj#qA?ZX^Y#v_S1QFm`W!@c6efpDF+^ok}_~V zM=%)|J!jo8j%gN5J1Z*}M58G#fXJ_#^wkHUEz1vu{kP(@$8NQ2;UvjS&Zwf!Ro6(P zH0@h+k$trjO=kK~PbqRsPW|z#y@cn@SzuaDp)^23m38!YZ9fRu$mUeLuM)#9=2g|1 z%B&uCEUeNz%0PCA&r+p_z(UyFSH(K4s+G&TQ_U62G3J<#eMNc6JF5U!A!<3OcdCI3g8U zSv*-yG!O0_+y)i?^|wWcQ=li zKUgO|>L2*D5A643wQ=!XFg45mV`}>^BoT!2VYInVlW`)ob-dxDz1B)0qvgM!6F|sP zF3Ll`eSY6ew-ljxq5%SokkXK%N!XgRr+;i1Ge@MB6l z|CWtW4i(WZD23-I98P6*<2xnz@wGFngiM4(N)yRN9RXQxM<27AVQ?g9#K1&=GLjdP znpR&|@LlX?DY2hDp@QWrnFP7TUzzoArRw$W)+8p!CWQu&(6b9YxIMvA+9nb6pN{lc zmHUr8(y;ED_yn_hIu|v-!9%X>xbdAXU-L`cbP0z_!LcMh7wUb7vl;J9#`)TV3;IFE z$*zQ^k|tGrX})UdnJj$%4g$jWBZxRuuk%yx+vRb@srQWae zV>Ik7dJf&jzNh2zrH;s=S`q<9P}Q{!bah0v-V%0oX!jK3$WU_Sm*N7A5~U=Bdunt< zLW6@`GWC%wmb22(4B~rNqk>Z-^c2cEW?FBW2E0GopWg|tM5$}YF(KLa0SbCudAUJs zET+c5`mXgayr|_fz|M1})nq`OUI)o#d3E{e*B~?K32NhdkSazc!*Da&98Qy-TS3q_ zdQ#OhsbN3jmoQ8WfvoE_+@ zmn1CkJv!lhqW2rlV)>eTn!xQ|^-;+VB;w5qKZ6|1+9{F5BG3HlRvkmH9!ty9dtnZtY1Q(LQiqqNpj3i`ZCwOIK1oS#aWX)SIqs6#5ZIT5fL~?^%{)5jPLh@f5or zBF39LscaUfu%nba8PYpFKmWUyE=545gD0b_V`TeNeVfIUoN`}Gw+4Z}m}UjUNFBGe z4=|HPqFC7jBI+UCRxc zsTKD!IZvWW5g^T&|9FAQ90J4I3QZI~Odd{Mt=iJ6FojqMP3Q1X_=^6L-n%9}PfhvH9hnQ1`DaAyff-I$xgF{4%L_V9Xw%0x z`PhvAP|Tdu=qZC+@jRF$%GVFT{6d_hPakUvlRuK88!5T0dn`nmkt&l zIU0AOta(`D=pg4-%h-fp#?ih~=kAR@Wxcym<&CKqFD0qCO#DG-YQ$ed#<9M|9LO$U zpyh3v?ZgK*2_SvXN2Jbb3W_S#{+n{sly361*3o_X-lW6+5%uoU;?E1;1%X<>DDJ-2 zsxIjvi=;-gn_RYYma&YL#z2>xpVv9i#lk6`h4l=p)Hr+L^JlR(TxG#Ao=Z` z;;?U!eox%?*K*7MEvWNbkjS9cFTR>DLLA1Q2ke(nk=e`vyCP^UcAx;0^B z1z7N2gbvtXUe<=L5p}Q;mt1Z%3g5QbIw}h_SKhfb5}c#E$)jZ5Hf3HW=*pOC=ufJH zBZ%*cV^pU4$~znK$bXuS2mr!#6M)zky!*~>nho8_SqQMRL_E)oB0|l$4ZbF18(PZG zQ%++?M((=2p2u_eqAn73>Cj7odot?T6J*Q=@hSaMUwd*m$zNnu3uoLb$Uw*a)rJhe zTdAUH-1B`3M53m5HyP=2{EapMp(|;xk=D_Ww zOq=c29ct}ulE3Yul)rx#?OF&J@`5=vC4F1>Y0c_C6uL{%4P$(H-`TlU6hACCE%TT+ za16Pb2$O;>Gt_@hq-S-i-9;l5mYU`>j};+qwJBl+N)qD6x1HY+;k?$_8?++sqYm7Q zywx}zSkXbJj_E0$T_?7yIAr?$;WhEb_E=L?Xmg;ir^{Q|ygX7$BQ+lg=9yQ^0RrA& zc~{>W=r`Qf;=%(ykyM$qw81rw8GzLrza$rI_))HaNcq2LI2vyq+C)aYq9J-$hqU<# zm=#0T;CTM(aj2q8S!p|mZ}b$eK$Co9q>k+c!SV#1$!$iejHXs>qke|hb&EI>$xd7< z(X&9aEy1$UV+TFu$yj{C?-NRoX(kx-+)N=KG>x=;Z6bg+ukX1d8u%um`*NA0*!MW% ze~7{Os7imFneZ9zl!L?!C6k?8R@%IKv3Qp*j&|;wsM~I^NyJQXe+TZ^QKtyND*2GN zbz^O&M20(cwfxw^VE@{0OqPHu-LOrAiG+ zhOnTz7~Gonp`N7*s$utFp!P-L(s$A3l20CP=U)pf;kWT1|-Gy7VN*qen|z_&Y(RGu#A#ph|tZ*f)kb_<#Gr|ZkJj_ zdR=vD*yy-!abHdLr&dk+J_Vsb=SXYp*Ai|q?^rzv6J9o+OXLlgTcakap993)K&>gJ z^r35-jxQL%aj#-j($Ff8*C&xgUW%0;--*ByO{Ww{DN6ux7(T5aE^~GEiVmckw4vT) z@Oh6Ae{!(fIb%;C0fiYVt`%*aw*Q0L<2~AEfIr3>A7N1kdVMGMC_Q^)_CC4Y%GR0l z1`h*4wxi*B*J<~N_mp%1pR%b*WMObyX7t+E*dxD;E?_0}P~OwKJTo?TpgRl3@#olx z(duuKwZ;6S5HuZHx#GBUyI$m#<-2bYNXY#Q93wS;%WBPBPItgT-wEpO9ZjTd?HpaB zazIYPs6bx5Oo#bT=7>lYdUIz+S`YEIcXh1tt@BZ+qLJu*#WXb@QE`Xw@p_WwjqW9@BL(t22(~=O>nfp^4>mHt*OzX zO`fUb=3Q)g#O|F}Ps5&ks>+5HK+A=Q!fx^JXwbImx0KsUY!Hx5MY#{~POUfk-Nx=A zj0dGi)$I}M`%7<>aMe$)!UaiJOf05~w{Gxrx_9Isodm z3<|G&`dxX@Gf}OBiNjKsM^EyD z_{4o+HC>6ev3@#p$Y&0)kq($Q8Y8T+J|r>S=&z@cvU7rOHf8>*mhpdHfS22^F9b+$ zdp~>yHQ*o+w-c`@6x=B{k+x?iw@Elcu@kHjK|h(c8Fixe|{($$ey~Uk{jWuGZq-iGH-p&abZ8uIQTrvo2I#?S8S+2muGFFla)Te zL(885o+mEZ#CiNZm8*b>PS5Ro4JYdJxCqqRT9;QFxPIvJE?GuK1q>y@-X0?xbfF!O z4qa>(&Z4}qg*+`7 zOoy+wl{_K_IS{H4v2gKVrC?yP{-=%G(}3xcjf(o<*H(ZrrlSk=;MDm0$Tzg!;nxw} zf$@|aK=aIQzOT31wDiX%4jKY}wwIjV1+POGkO7C1@vGMQ@OwmEU>=q84Eo_Z%LI3O zBJk0nFi~)gZ4tGBhILb_)Bit|P4I zyX`IAfLJs2APk?2DgEeP2w|JdIhp|%0h-xbJ7s+2?z{+fpDB4M&q-=qk)lhOK8L-L zMaa0mq?JKYMXyZQ?%KJR6&gR}5q?kMOK?oB6!#UvwE|xI?e5R@!H%LImg{!loqI&S z@pV1VSQ`CSn?r+CL5MC>Gvso@a{5}?C^X)~6O#twj5W zrwH;8s4++V5_&r&ZqSTl!!UftJuwkn(=k}@wYXfP5A?9>!yIZ-*i+eRxb5y(qCZyg zERW<_4rHG}#RlZrIdC&u?qoiW8b8H=UBilS{8kQ_@ z+kvnjzw|AB(11YEdEv}A^JM_W`ej^$&p(CMkt0raCub5xU{_SaJR>cQ;kWwX%EpJA zv#H-P)~H&~OQo0m8w8Lf3{bhG7^_3%)}2NNJAi?n%S%Y5%UCTkE;N_F|BHv;-68f1 z3HibMXQP%)V+U=05({5wy^lgQd=QYL`WNe8z}WDEwV56u`|ZjJv9VW&?`%E}JtSo$ z_m9`zdyiRTKFUvgZf9gx)x6oMR7jSQVhvbg01Jv^WW0zHZn`KLPV37 z>rwV)wk(+BtvQB^p@ObXvA+LqC>Sjs?q*`M-BT-w^j)b*+fEQ+<)%uSrV8(;UHi>A(2#t=v1OvCupK|*5@!w*V5#}2 z552l!Rr^D&iNkNbFrAj%O!uIt z+h_5PErhZEGK(y>b2S1H{`#W=)kE=lc88=u{bYJ<;noLxS65g(=qsvtcUEhSq-vXc zH~KPxOgRBO2UbmX@WaK(8M#6~dStd7&J& z3(AQY$2@#%z@~M|{a-(QL8V*cO+X%rd}=M-FyC=liG*SOM6~OFy0u5m0Xc-Dz z$69>n^U{F!;f8oZpJtb7j95kgi63m^cE7z!qp~dpP5$jH;C-Gv6Jnhci%uaA$fISkpkIZa-yU!G$JEm@43CTlW%0>j)X!m5YGB1Rf#^~J%zy9 z%UrA%O zcE?=z_#$Y7XKZ(%sz@0|v%>7bY!qY_KK_J0d4>Aal-ZqM{S!3sL9u%)y{G~CeecI>7sy8R5h zjUc|g6JK+uPzZi{DBLH)%iJTaEB4(?6FW-FPs+I{L!7zCF zEenWHFss7Vt5eT;By#&+P@u^WfWZQ7o$w+B^|-ZRC~a9FNgIjA#)XDzf%-|xfI~U5 z6*UoZk!pY=DIrY+hV2G#(ac^qGv2S;6oP`1vqn5r^*QX#<}x| zN4U(iwJ(+rQcy$neKpi1a6cQC)7_L%gKP^1I}cKoZD505dkC17xsl8uKV?t}nk~+W zSY;HAt%$7H54Ea7qn4YtOn=qc8%{KqNh_J~8R?nDPD%x-q#tAC;|j!ooT|hbC`G`f zL~;9g{t5)7XtflOv{6LJ<=62+L=XsKS8FK{Q3__!EA2TYC}Y{&TF`7%!+@kZx*aP$Nmmc6s3pTBD7^k6?R6w+2auRANK76Ir|J$i-#O z|JT}AhQ$$dYX*0BcMCqaI|(oWg1cLAcXtB81`QS@!7aGEI|L7I!Cf=JcD{R`ySvZ+ z-T5=q)7@3oRn>LgBlVsDkl=HxohU02sPe)TCXND0J$z}sVBq4(RMocGaonRbMp=`$3#ZSfGiNL~Rs*KxyfjO=NlQ1zekE=(vHSaK; zh6!0ywTY^(4*fcJQD}IvhQY-G^Hmg^=sQ^o;&t;s_<8QaY+SBlp=KaWMbMK^sFPaU zmXE0=rH32m(S4}sEMn>-jBgl;$C2}9#lPki1Rf2g$Fi>qmfJDS#=s=(`G^Hhee-~w zVhEFfA`Q9(^!5?rq#w&T{7VpiW*FNj_3>4s)s6*^!}J%i*|-MwZ`Gqqkw zL+lP>>A)r0ANVZ1{`7}AofI=EJ0PjK2$7BOHM&L()f5x)OMQcIDaTm@DrE63a;5976PD|DQx4Ee;>xAaAMmoDE}<%1li9Wu4l59nycFx7cLw9r39Ke!GR@_48eA6Dh*X2Tsc5Se5p=9|qiNtI!r4Xm4AZ)o`9a2MaAspJ&%Vqn?^ zSrlf{FHs_Kq-vtd?<|k!4_8M%{eljCUan=icGq67rL^nIFQBnO(V_k&+*x!=`^aEI z*5x%En{cWwSat<23ApT;L<$TM%rF+x*@7Eu>jnJit6sG8z9OF*e_W01C?>C-n@`Tx z{Ov7xKOLi@u5RtmDpyT{usdDJ+MhAK)!m&o*CEdLVm16kjXBdD{s*6L9)@>)nd^Jf z&m&i0AND98?qp0#qqNaB(Y%f$kPzLBe+=(d1`IzbGb%~_!a1La{A|0l0bf2S{gq%+ zvv=J}CkyUfEDiGl0(TJ7W*C~J=y*fV4_Cu*!Bu2Gw0zZ3rq7f)Hor8b5H7mmo#FHA z6*ex(t3!U_>twEo_mU344D*D=^R@)# z-=~N+D?5f*gdfp2#)HxX?Re&;$ht1#3Q2f2Y6y9j=_S5^?RmRVx-a`S|uQ;&}Fm32_!;LcIJBigeehVL*Pkjv2VI# zlvH;jplmjuLQ5=&@rtWQ2vSuk!lCXZZRo|LFi{*VDcLYWGpZV8>4Is;lf-Zi7}FNP zC?uPX;i0w}*=R3Tg6c?f*VI+k^4XN;&UJVMne8OfaDVTCXl_sm&ynM&B=m=p9I)b> zvli5))!7g*WA|s?Zmd;KNoFwPn8|=e4)}~U5)tWlRw-n}9G7PqvE21mXBfn35j$T; zm<-wK1Yh_94nkMixuzqCptUgI*8(QKTQ}q5MQpn)VZ|?D_DH>KGPYqke^`rc`inN|! zAiiqv6QFSDu*>m2O9NsWQ60G`#p739-w=qMF$!KCef2)C7=Br-*>&MGg*OeZ}487z-KslTrC4)mx4jKm*=%wG%9<*##24CGnfnlnq& z4Gdh+<*IEG5nCD0c_SU`pFDOu#p2atA2FZuhj+ipyp*Ed<$L zo2a1B|LFd#QDQf@W-u_XiWt{)oaY1h^29fk84s}FKqQo@lGN`D$3EPqYP~(qYM%Wa zIkv+gPu*t7AF-qNnQ~E1Zi=0| zz9)Cp8d_w}d`Gr4My!aP0t`h`Tv3wh&kPWmO~OcbBE&54sCO%z8kRm*q085zz~w(; zfPiP{{39*KOJ-sfO1YzBfOVkPO%!TFHlEmw#@hVbxfQW207%ltU3tJ1Y~xPVg02Yz z#L)+)Q_=~s{x+gW@%4C2{E8?zUo>R@eq7y36dWHhi^yyr`Av#QJ9TN|no@@uL~pdD zj$y8D;*Vu}58Lz$*j|B;uVhJ0Jo~<=UlX%Q#J2mzT+Zv-?h^7q4o#u+m)kI2ZzBehkgEc2z3+M8Fse6Mmsd4 z?4hGPX)+<+;^w8BPWI`;+>I>K%TX@JCv?CJLLR1>jiZIYiC_be*AU1illHizd2Fqf z9djPnutmOGR2U*x?^Ssp10H3de=wxPG~MkTjM()Nh94O-BeXi~4CXkc>q3 zM4~*S+@NgkrB}cw-l%a=Q`UWv1tklTHSN4-mD8}5HRojT9IYa@R)?azb(>Efk%4%$ z>z^rSr}!*gt7<1!fA-=+Z8fuwL$$m~U_Dc*!C1y(0SVQ}@Bmug4AC}H@o!P}?Y&$L zo~bD}Tmfm;%^Qo|Com9l^1vnXE@{M+-=wTffc7Fvty*iFb;4?sh=+phgdy`}sbGKb z^3mJ;{9}CH3!TzXhg{6auxXGeLXXX87-l88f%&ks-LP!yOdsBYS*ImC?bx)u5*>N# zn+YSXOb@Yt3T&Hr!GgxNKo`GL^na4=yQ-!TzinM+}0iw*w^f{B1$+?*coSLCb#Q zkylJla*WTd<3iy!vY2U;W_k8m))b!HcJv));>Cp z9fw{qzE?slCV^5icfrooCjL2DhNhofO;E|4*=MBAnpd01Mt(>diSAxHkWaC^B6SD) z%!jlT3zGq!RyQf1E)&{Ybil$(B19U!W6u@I6GF_6GZX>jLCv!-% zNtl1d!>#Xn>UEvZ*_cIP2DU)4R)V+OP$;~=6Ws2Qq^^*^D-5YzGRMOv>?lwYTSnCg_Ta0@8U5Pl zphr>YRG{|>j2P3FA_LS{1l)yjHnP|^SJf1U`j#SSQ4d364Y}?t!td&4%KdlvEkFEs zff82GGFd%sP!%l%SfB#6N(tYg!N+5c#CDCrE7$KPNqTIpx!0dfG5Zrb#ZM!z>_Jn^@6@uX;{Tb~j3_iw~8TbbZWfRGxZ7|SP_oUbC_m5^1Iu$GHlyxVs#uLH!cy7hJV0C;mbe>g{6dme z8LS}h9f(z7gm9f~x+7B4@o};I3rPCVCkOm8XWnZ0vx@R<$@+Frk zZ5&^3kT_PZdovxJGEwhuxf)+K`!xijlZ#V1lk{W{9C7^2IIeFU_R2{LfIm^l^4DP@ zN=W=3e%Ase56iqGTcpW7clfErRZHQ;BcIJ)g^?g~o<16n`PP7d2Z%-UXRaT@Tl+*J zv_^REP0SJzG^gB%AKiDm{tVjbCwEzDzXb&PAB7RO4C@!bMs z0U)pIdVRyE{Qgd|0i&~naxl`p=?Z$wRR!}>L)CflrkS%>pJ?ln&)J{Te>?2FBCJ*Y zVjSmTQfAtl5U{~5E=YT#r{sorZ6McKOaFk=J2Lg6vG>Ma_%J(0(AMsJMBlEBp1={7 z&=_n9s>pynj4}BXPW6o9O4Qdkw^{kcnV<5-g#f<2Rg-7N<%6?WGF`>61^vuPfIexa z|0}hM;fl1>!Y8Pe@i`d@OIlofg`8YOi{(BE*_(&nxocaB; z8FmHvJB9j;k#`ogsJ%|>q0OIaOi|k};{hI3R6S0IS*1G0A?bBu9e%j7sb2k@#F1s? zhi9Z36K=N2&=2P_rh-u*rH`nT9oY;$kE6iX9YU$W#U) z9=g8V;hf^m6q(tGe44F+XYHcVXHuTt2{ngX3V;~EE-`i03mO3|*9D8ej7ZU@93x`T zwsJKd&KEsELdyseL3o2;Bz-hu_06rv8m~4=p2yo%=SO(xuFON*l+3D}ckvBrCYuPt zYa?9eEiyPEY{m8Au#GDSg-sz6Ad6At{G};VYV6dfin6Nmhpf@VtH)vHVry|mAnI2C@0?lQhy}7DXYamSjVsRX zis=xg;BFX`V-y@xcOG0__C>E&^i&9WG38E%IDwVOrfLKS2L4_skyrN#5G9M-eobTG z+_QbSSrvLj>}^9RoB8bmznx8MFg5W{lt7bI3{f1TvyaImg-OZc&ZypRE*D%dZ{G{Z zkd%1=gYz`_(9Pr{CAkP}7H6M8x=h*G7FE4W(uh=;uPO&V3MjJ;SzH8WeGT2O{o-_W zE8+u}u?80DW)oGg5N5KO$r)HD5pH$kJR9sAyE%V-@eshpf%8_muj@R#%Qhi1rC%^6 zGrJD^r~cOM&c*awF*b`igoiVV(5h>ZU*x={kf9dLwM+e(Q!rEUDxgbK)?fIo6n)tFBTr_4ayy&Y1y&zwszah?9>-wgi#&ocbi1^+lYm= zRT@$of`&wll%AH4oFtqQ8$tl@jjoDk*RTa0)R)I%4bg7sIP1sjGTQwH3{!j$c=_a4 zx0@dg9a=UF^QTZgrTjhel%=ht0aZ7`T=6%?T~ucJo23qkDH!EWaMl!1TM7R?8nN}} zPTWAc<=@vP1u#axQMgB@f4}*{_|R)6=!K&fpt^{xZryjK@z6(@;VbYv6(;Ky9ckhM zYwX7QZ#%`y6NmH7+VSFE5wSgpg&>~HpGFUshFl(Qq;bYj`D58FMW<@dYm*Ni72|0! z_uc5QZ?K<>K<&gOTea~xmUgx2dJ!A=8M#^8;wMpexjJ1`_jzmwbmx-*i6@=Pq^q;F z*@ld&;6a+hT=&X5lWhaEn+{c&cB$k!{_Fp+t?6FKRkznBsUv z17S7_TKrO0prznhTbm1Mt+%pd-`a6NYE_3|#Vb9H3d#fnBZOPWniY?94_9)4Piv3S z@E#<9aDv!ufHVmo-6U;D!AnA|4eC1nHjnH>*AEi5m=p(=>;8ZNy zkrAwLL>yn$N6ZTlFbp9Mp?0=;qGWC}{u#<2wvgynr#cmZ1%eeHUswc4{ySRnlMO`S z@8LznOqZDroN{HwNsd5;%3jeyg~7E3-*p*P*krt#{CW)$7WLezQ>P?+crrMz1tN zCZXmhHDiF9C-(6;&X=%&e99BMJPk8y~;>=ikRFf zyfH#9A25i~{MD5Zc#nF+#An+GT|kFe7Y7|of!r?OeFX3QEHoXMa zJ*UUnqZU~a;093GTvR-u!5~fhUg7|N0%qY&-rLNz;@I-#hf9}6?YvDjcbqRX7~Yk+ zo@zo+_S9rYOJveoUx)sNex546^gR}yhu^)rU<%0R?|EmZ7uYOgyKhvq=KT+lWxs+) zIo#&n6$@RBph0hcF)7sZz5RoP5@KbHUv2P&Zt=>Oz?LVMlCt%2s74MzTp<*#fGgb0 z+U_R8<}Rv6iN9%{>yPG7M8cVuhBGX9mTCvH`w?l+Y_TC9FCo5t-xW58hcAKBv~%2S zSa7&xpD^`m{@NEk;Ei}$)VcS{o_*y`%l_3ItwRqCX&S_Q*IjtlLXEKdG-|TWVX@rb zYg9$SYayPzCh{TYSKE&F%WV4lyeo{eE;rk*aHpt;%J|P`|Md4hQ9yq$oZRh&=Xp(b zBAXY6q)aTEldP;Kp+SxAouhzJ03Dq?NW3N`WcUjk6e!Ih|I!?T3{PRQPKnnjDQ zb(TNPhse_wHO_K%c2SWbscg#>3z0SS?Bf>>1ek!3Z;X6QBpZ~~dEHzbxXi6d{IMii z^A(nM`hY5d!l&Cvcs~vU^1vbn>p0z6` z*TYzS${=^XHfgH9Wm{M9g~f zFMm_0{B{L<(qV<|cO`gH z7*;a0MKy}s51p%2H{2IxujmcxV`FvT(9D75)@7T?J$jl%gJ7;ZeiZ}4#*$aHF z4?AsCxT_E7SP6bnI(Elz3>5fSkei{N>+HIthtqieKBsS8=Wy}4=-@-XMrs8<4-)<$ z%iHbDHq`mhiQ{VB^um86<^pZpEZ_a`ii*XSn~%HT_?%cmDf={{k76=7-5W%_bpUnt5bVaL-F-E!2m=RfWf>zrY!fB$ zY);R_z*7>#BzZBHf7%G^4scQJojrV9t_80v%E$#?=X`HUFKfi-V zl?QF&GlTKuUBu!R31yQXm&TBoi@kk(^Bj2e-IPi~R$Fb*+^{ud$)}5~6 zM1XgDbiiNZ9iGfCOIIjE>a?f&uU7H=38$To*)~BZC}Ki|?srXU66T4n_>PPJD_D%z zT$5z&nONa=W)c_&wTW2$(C&CW3BWKL-9-E#UzMsblN8kU2$h;l)v7z~rU~`XZx(qD zU>qRW;_~C-g4$JKE_BE6&EnOl&SsBHj*T^MHz({hahmKmgFm2aQ_vB?DA=qvn@jYJ zabBpNtro>Z7>kK?P&&_~iRwxueMqM=Ux!ZB_)p4Kq`lZ3-xbmQzcEjW_3cd4rEb0< z!L*Q$H%d9ALhymwCwqY5)M5z(YSjpli-Ef~BWU^d^GLoi&^7t0paUGU(s#=8uE90d zvrd~mZVkOO@x5_3SW_Q2%C6Y8;1iC^VXSV82|pePQj>vXHBKuqrlIsKM@@|CQdJ)* z;B~^d_zHW!YtOX4P?4Ku^oEu2Irf84yY3T-+K||It6bfCQdu#r(lPe)m5p@o7N+@e zwCn6LSY^&Zm7EnGc)-|9qI^_=Ovgo>HsYLaDOKTQyEDD4hM6byrRxwGQVi! z{e{udksq->V|2#e14qA7qaGz3%=@>17gu*FduVx|#QW4OQ^<$3No9nAod%I*?tA=9 zNbn-n=28S|4coy217W+z_FqS zA>aJ$wLE{>0&5y7Wp8suKND` zN(%|QNsPN117Of7Q@2fffC8J1r%y@ith9m$93RF+eX9Y$bp+cpll9GEe z44No5GEJ3e5cRkDYD*19Vq)Id!eyIZxNu?Ps|=6RaBghQj%3}_ z2~DpJC*|56BqpUG3}hc&F&R|BHVv6OvZQ0Q1k$Fy`gova4`rPlN_V^qs=Ee%V&|N$jqmd9jFK zX-OI`Vr2JnW>HkQ9cwYoC))CXs%l)SX|IXh0lY)M4l7$(r0KrS*1J;ZM#^GQ4zF{{L z{FBA3s@jV{c0xXs|Mca5S`GphQCEw&otic@pl{X^OEFpD@nQS$VS%p+tH`_E_aXMhz6yO#<+7KfZsrnq-M1iK!wsL^xrVHEMV70CT@`vx(e9edXE z*fnR;^MvB>oS_&N1f~G2Hug05@}6ohw`hvL5XO%v=6IH>>9@Loy8KtKujr)wITX2f z{6$o2x9`qYy&$j*1u!cFFRm)4&^>aYrnVP%uTriT!%rJ1o&~Aaj^`@Y>8SVbxXzBS zPkQfvEepARX}m+(2wVH zdO=P^b6WL;m%HQox<&yKcde}2ZyrbL>0)|5By79$JF<;$gWE)jwK6tgIf$G-H$oU-!*9=Ca=YWSsBi zaU<_%$yaFLdPn>Z)u5NyR#_webGT6{wts3Z^JEeV>)UxPB6xTHDo6PdB(^x3l0i1*inLWK zjTJ=(>#pgbRlZXL+{Zw zsX*5rr5u40Q?GXgkC89K4)*1j*V3g;`k~qOd{+;|XmvY|7R$4dCQa4r)z8nD+*;cr zy2z}+ef~4C{^v(rWaw;4{Fi&=cE$APsxraWO6@B{d%|uzPA3U$yRPx$6kRC+huiPx zE}D|(V^IEl<}7M(spszArmyp?oa6^x-ER>6Ejf^!Tyzy52+ zi9$#hB+*kgF?WnbLnh5D-Z}g1pFv``9mB1qCY-6>u%37)n%02uXx5mjS(t(`p6!QRs^ zaBZLCC^*H7)Ub3$7!*C^TETWG+X-G-*Eus+Po**zxTfhb+dOAlB0lC_m&CWMyYVkg zz&eJG$M9SdnL7vyFFWTtpj^2prK2u$d%6tIaik6XonzM)$gX_B?qa*SQclJ4`SHrP zp3%}zX*rEGfN=JwW43uWtyJS=Qhlh~ zkhI!G;K&QQ*wGqYGvrkCEDSkUsk!2Oyi*=obz?B<^ct-M5bC(Av-Z!&Nd1(E-Ag)$ z_JHMg+TwfIhMN)^Xe=(;j2My5@npe`YGM)eAqgw{$DyUdvyp{z1JW8d~x08r(Qd6wm&&MZ`lcfUS18 zcDVm7GAKf1SiLSsG}*ExzbsN`Akgq+&yQ)9H&#=7h&U?Ac*5P;Y30kqm{`Dp4jE^P zk8YOLRyq&GdxC`Hgiyi`i39yMBb$f=G?%{v;CIEl9|j+)Fyp9f!%tN&)< zIgpZ^SY>1oTkcjOeB6Dv5#43NxVUVvHy6G6I_~anyS!$wcfgs@^l^6KR%}H4m}!o} zpJ&lmhHQ2*eKY_%z@08{yJ3L+-65muoeIB5P(b^a#kT=#lTq_5R=L@Ge_WMOUaa*( z^>9Lg$bmHz_SA!ec~q(m(Ul*%NB<@h^wAwD!9w3rP)__##rijNJ2_o0hS7oUEkS*i z1biKmgr`e8%QQnKzWA+VYsAKsi@Rc#=ls*-LM=b9nebXqx~tXET=&9zq8;^p4fNOoRw{NZ%++HIGW;V|p|z&V=$0ejDX=cTJ;4SkwGz*p_Zll| z9vQ%8CX77pC=4yuVKjbwZCj+pMw6qfNN1YK=72X=la6StT8Fu|9ASACM%rcdd^#Dn z0#p@wpJ`TYWqLdbVo6gwRM8aBBC7>+d;nd}b1x_h5Q#N_M;R>^Kd?bEJ%P7+U2zcj z8H+n1nzSl0R-`kb(gstX7$tosAIWo%*StLu0K&EWQ z-4u|M?*HqU=?_G+`w7&77u;)7JgqaciJZ3e&4K?@e4h0p5)q*458{nfLrz~3~Z4&yw0B2!u-~a#s diff --git a/docs/interfaces/lite/pics/high-level.png b/docs/interfaces/lite/pics/high-level.png deleted file mode 100644 index 73a14e0d73db9a276150b0c2affaf332b7ab0331..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11595 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 R1w=ltjM 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%0DO|0SYW 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 diff --git a/docs/interfaces/lite/pics/substoreProof.png b/docs/interfaces/lite/pics/substoreProof.png deleted file mode 100755 index 90dadaef37afe2c1992342fc0bfb548e14743b28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62165 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

    v$AEl$= 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 diff --git a/docs/interfaces/lite/pics/transfer-tokens.png b/docs/interfaces/lite/pics/transfer-tokens.png deleted file mode 100644 index c6635a30c8b57d2f1765a3ba6e3334489a7775e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26410 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 L?NYjo;nRNsuCn5^ diff --git a/docs/interfaces/lite/pics/transfer.png b/docs/interfaces/lite/pics/transfer.png deleted file mode 100644 index 7642e996cf323d1483ce8b1b3aa1efb85b1c1ce6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18492 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 diff --git a/docs/interfaces/lite/pics/trustPropagate.png b/docs/interfaces/lite/pics/trustPropagate.png deleted file mode 100755 index a743cfc72147ad521c2fc5be292c90de47faf6fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49750 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 diff --git a/docs/interfaces/lite/pics/updateValidatorToHeight.png b/docs/interfaces/lite/pics/updateValidatorToHeight.png deleted file mode 100755 index b2c9349b6b455ffd0854bccf92819937f98a25c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18077 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 diff --git a/docs/interfaces/lite/pics/validatorSetChange.png b/docs/interfaces/lite/pics/validatorSetChange.png deleted file mode 100755 index 16dbf39be7ea37ec240b429623df535e10c766ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36169 zcmeFYRahKN)GhobAqnno!Civ8B)Gd<7~ExW4eoA(ySuwP3=HlrgF|qKpYP&)|NXf> zH~myS-L<>As&@6Nz1Ip;l$St)$A|y#zyFY=Bt@0~`|s2BM>!An+s9R{jH2?t|49Cm z68)v>rhl60tg9wPFx>6r8d9POyR^PuxfDh7t!W9~g~TPoKZxGtB=`(JVm%aBQp$DB zL+F0ze5IVJ1Hogm`#y_@ZPRS>Ws>b0%qGp6DjRGM2Lto@^C!Q*!onnq=5RD{0DW^C zYE@kl5>!-J*pGYgpZ!4yM8E#G9+dHy1RAvV_xJ7B|I>~nv~}wH|8Hdk4i=z4f<&Wg z@V|{dOn3|bZ|(n?_`e#9cY3&yf&xlWj8uwzNhSIQ)uisazZVA=tV+DwkbFgsroI`` z5PovfgxECHU!t<`CC2~@s{p?yeChWx)WQ-^FLYAHg59 zDHK_XATLrF&+dh%B0w|(t99k=| zN)5Ex)fJ(@n~SZm{Vhrcr|KAWeSQThO4?JxYbtlgV-xIe!IN%aUCETTK}GLsuT)t& zyQ58;2`Q2(Ph1&WzJDrPn9>C1P_d{$R+!I1FrR*bePP*fD#XKqWLop>NX3!gY78IE z!!5go#$=>oIwqB?zY?~h{SJ?23Z}y^C@5B{&^N<&k15t%@aA7_-YGVgp zZo7xY$sR2t3OJKcXW7iIYdY04Jl{_iM3O)sS3d>Lbkl#ho393xfiUWkngt?{Y&7xk ztKvl@NlG7hwA6yAEe#+Ok*{|@`9ybjUuZNN@;r{dliW|Lx! z>eegr&2*+0Rr6ic(0PW2Fn6CcXDff26##4}frgk~#;=k2dh2Ci_@YJWA!vCzZ}vZY z4aVqb?em*v*~HOuzV3R910{VbsyrKW`Tn~v=31+tyq)nJP!xXpYT)X%&5>QbKwdm< z(Re(f8_w6Gni?bW3$M=M8)>$``lTn=nLKk6n_}kLPS9aGltiYl{uxUxy1ted@<~uD zD)%N^y~_|Ub`uG1brt4$!X9=ZBI9NVW+1YmYdjWz7jI;l9{ox-D!;oisB$Xk7L5Z} zYM!oIP+yK9H?Bh-#{V2`R+Wq~c$vL${fuDqgz`g5E8#v+lS(9!aPXE*g4<&cow=T} zWC^P{Q^r?2h1pMf48g@#yU4tM!k8X^zBC%x_^qY26=3(^Y5;b-;}fLks&U=4RgSb& zZ1xuzENeE=z3?E^*_!nKW*)To1`?BVa z6_(caZC)EG$0(r;bX59wz2epD#Tcj!2lIyY;XUtIg4<9#(tkWGDWk<{DXzr_$%N`Q ztD!P#I;w(Kv2%-yLQK$}h}kao3u56Av6D+;&F^Q;DcPH7K!fn&&3>~T8YY$OeS{+A z)DmP8a>lPu_fORTK|b=$H^q`uJjPAi3VnGOo~GO8^Fr6Z)&DE8l{xq z4A9pf$6YK!j62YnnlVD5WMm&v?igRr%7!$vDyLZY#S%;1`ey zkFQ<$6GOsre^7?bNe3)meTQ2*D%s&0?r!AmUSTH}REA6wWU#w*!7@k8pVAsYVDxY> zyxHs|zfJ5XOiD=->Q2g`Ygl!6@ITJn1I=~Tx+&xIOIKIk4fuMymh3AJ#^{UL)plm5 z${N?=d}6HD^Vu~3Wc8;ZRlRh1d~QcCtMlkZOyky$#lisJ^!B@J8)Ke8TmO{6Esw^e z9-U8$)azU8bHGPbP(MWD_s}Xazogs`j|nGb+@vt1bNlaJHZIi~eLL=@w^&~I{w#=* z$}y2t*3>5YQXA77Fhq8=4e<+`m{Rv#Mo@89_)H$D48q8pXcZI}1lv(Mea3>f^kaA;MAdi{@;E#!W; z&cW{PNv4p)2ge%6j}B?>6HP>Qk&I)@`9`5< zrK)$3Rzunt`Pbj3ty$I^g5M)XW+M;hlZWwbN|iPcO@gRo++DUmSKl1h?2q7sFRBXm zdobM2mqfdH2eIPT>H>$s{|<-G=O#0d@g>kIUHcz|=%KsoTCWxGAuf=DIRh*BR>;Jd zG$n^%5`zU9-%uMczNq5 z^yh1oK;5?tr|3z7fkbjzh82g<1xnxv6GoxE^`rR^lY;4d(gZu3#=9#(a6Rg)Mg&HK zFY&(Y-jC0$wx>77IS`AEFU-?3Wat+@&P(@eao-w=rW930hEDhvTQ6t+7IvQ&8l`$g z6M|P4f6>U1#8Sh+us|>(f0G)BY+Yx$lfCtyu-qzr^?zBMshJ!84u!Zwr+anGS7$=B z>lbV6&5fKkT>fslLC>u&RA#Ay*lNX=8-Q$;nG=di=+_S^jV;J&{vPY3>@+qb*?a@W z%9IS_bGb4p!N!}LAv!676l(ag^^VXN9s(lgSSqUaC#)a6wd%q@tsv|51!t{)4=D}FXN-q2d3WR%ytqA<>*BK9l zEG+lgf7W`4-fi>`1(EwYi*cejU%;T?K{q?Hzq%|xpeEVmEpf?UC1)oWe!S0Lcs8M#f3pb-PqUn`O9_}S(4pfhf`}`QPR@a zjda_wb!TivLp=5$uRSHHlJauR6ox;o(^}D4TRf-TD?MD?{}M*MzUYq*D#OawV@nBb z=>)RN4ZZpmzf%o0mHrLB%HAOpVRBnm=AfW;73wl&nt(p!W!-FM_4qsMIM^uOtQ*t# z%GcXX0G4-LPO~lszcfZ$FYyG8QQ-$>Z4AV2>#Jsa#(iZf6hfD!q`bQO6?}*LcQ6oG zac%$?g<@JT*umZWdplKOtu?Hx5hwtZdLcKBK9o_k#PM0>BW|z00dHafX?xp?+1z@S zGFDK`6lbr@ONt!l%ch(dJMAd*Bum~b$s|7KpL&Qj zz8bARF94nV$MtpBx-suzee>t7CL;a6 z3z@>=k(yCwJ*^eEyZ-twSmJH1z|AV^_7o3*Sx(%^*WwN;Cb_TlRv2{#o5P-NcF2-x zHNKr((b%nFW)w%4qJuIujDQS!sExOSeP&;u)GLimq1*_bZ!ii`h~uUJVcN`200*#? zCZWGRZO6Tytex{gdHyacgw}xV$HinjAZzH?g&+7yY$#r@-Q2oZT>jLi2;~@Ja(ice zl`R+dFdj*~lnNB@NtCiI(cj{-=CfSRLQ~F?-hw6f`05w~IdKEXUq+m5P8P$zd+JBVZ$`3KZ zIW-s$-Jz}g#cI)#vL5Ql%trBHQnKWf1!c)pQ7U0);)wVMWxpBz&~pdhp- zUVQVC^1KWMtr5q;4m_EDS&M}nUMjlB};C{G80s2{S=wXM?TfE~4&3)nc_mW%GDpStm^9AA%zDRg`Q8a(RCF`yr<8c2?SI zDlFYhSv@%u_m}^cdrCO(bdf;)C2Ao*%T;5B_Q!H4qRH9W{Q=J3*`^yw)8b`qPj!M< z8HAiNPNrJoF|-TN?rvz?Ogvd!W$6L?)2H6a`Nl@FXc!Ww6>4zp_ur-HCLgRdB}Ay% z1nqq&dDdPnSSN~zdP|+W%T$>ps+B}a%`u_ z9&IC+@x*r>IUH=Ka8VY;2@SU1e$9ZI2iFF*q7HCAsWH2U z&vFn~mK4{nsS&p-0k6Rb5XB&VL041oZ~g}My#TSd;z|bLJEmB*QS1n*i4iJF0UZ`i zP27_YSjsUu$T&6c;i|{Qj8B3_ZEt<#)T9^jjWVg*Y1~i1PHwE^u(CSVF==J%Q)%V$S_J3v#K9TegWVtG zA5%+oZ?>xiXHc1o;5Xaplh~h->QhqY7w3zWT1Hu{=Q7G;w*`(1T=!Drbs1BPE&A@>yuvy$ z(zEp#{dX&)lY2GYvCCQ)uV3ps3m>hEI6TtIK|Xw!U*W?)++4A5{F}#A-aO_gU9u^o zft%^2BdiC5OA@ls-(@N@7UAETq7s)&+!^~l{-A&wxa;*_`n?_rsTvYSv9y!((XTHd zWU+22n_51&jZQ{?P8`i89o^ha`2;Yx95%k&;E~k^7RSNqdftQ|Ooxrszl{mC?HiT;jDBlwdb~cma$sj94@taX zs1pT%k$}U~j(6Dbo#Pkun*+L8Mo-Slyh87nqSJ6P%V|5hYZ*JqL*eo?x?f|2)uSa@ zfLDhm46c2EpEI)s7D@4m4J^O*`3Om_CqCD4SwSzp_w28J3G(mO`26t}CdvSVH(1I& zH9|^jSxhztM+ihw1NMeK)CDqzhVjOmI=o%G=8hj#)%0zmEHTFkO-0qQxodAci5b9@ zGzJ?X{Rh(O2|Bi#t@E&8h`LpL_ERVs!#UYk$#s0DEHJg-K1Z+>3@dPsVpV0biE29@ zo@w4wp@aw4`h##xPq093GA6A0qSRRJ%&Veu0|vFyk9RX&2u2vbKYBV@Y*lDVK&pFM`oK~p?ZPC?a3d)+uL}Cb1&wev zR!O5=c1+AC42icEpRcr%Lzn?r^0v<_CZ(!lbdcd`eynT4+CZZ2HD%R0oqR`siMPxf z+sBlBJFYCpYbnftRrNv9_g!j3Z|VuGG*Z+D1-KEjfjwgPCP~?9DlC|o7okS+4FO%j z=&bJR40;rO))qMqFyf}r%;ly4J!C+)%Vx*L95ck%H`J<}ZYd3p7VACJ0)Al~Pm7F` z@HK!{Ocu+^Rr;~Prt(jtc1e`**1L?bV6>ncasLMJ9&f6SRg7_i*Y^Bf2W#8nQCPT( z$n*O01e1j;N6#jN|90|P7QBz<^+sJ~WRWM)u8sUyM-_`=9Yogc|Cb;4d?^WaZFT=u zV_!p65&cZi|@bX2%)TTgvh=CiRG^>GbVYSVmE{M1;OB&(uV4f&K3+ z@mSjVo+eSP3b}^O39f~sTF)K)FPeh|{Voni6yx=TchrasS=UWiTOHXu zT@75noWhR=bT8Q0mO+X0RYSJayTxFB=r$$6RQwM%qZKdMtH;64ptI*YcTpf=Uivs0 zomj9L&Cq`W*2z7Tt@8?y; z*-`E)S;U+a(rdf-k8m~Enl3fX`pONB0?C+IzwZ|To<%mb=}Sc%yshr*l5@ zMCCj0mm47wR7YcE8>+KmlPlIWf~DL-qv+I9+YJwBSZ|B#9ZBsQ1t;VJ`92!V$Le;*toR;s{9AH=7v6cNgso^+?q^As;IB~ zu^`b)Bcmj$4Q=uiLU>KC^Ynk?eNFt!4}1PFk1Fm|p|v$DtaSow(>a|TK6zGbhJ ze(`=OmmCyqAlrh%j>~crRhcAJrBf4U6o&* zFSYn>^1X?B`|Y#r*4y>sDWC6;n2*J|07-9c;71425=85&SW6_>h2m6Qr2O>?e?8on z2tOhfS+_e2WThyr%@FeXYeUTxo1EmQHA?4n#1reWU!gP_Non7R(;a$T@1%<(yXoe; z%)+I`ZpH?!4B1&3L$f$#nuF6ss0t+tj(B zQvdM$n}{hXNbzb@zcRM9PPfZ{ZJ1Bm_GW=Z?}u*E$y2EtFBBky%1TKvOfG5Mga|(0 zUo+_X8@;Nl?qMS=5Sy9*U1Q@Sr6!N&OYt?lUr6YXg$P?(Nu=nD9BLLKj!79lRO|OZ zdr11~tV`5O37h0O{^7Ft!>iL#2z8Ig@HMtafGMm=24J7-TgAP zMaef?#MkAiOW!g(M!dVqGfBNSRVX0S7lJp<-&9!hzzPbE=SAXcnO!d=emW+Zkli_N z&0el~hN=CCgll0I%iWVUlqmV{o&1v3s|%Ywn9Ntnqn#AHEnTu8+|@1fwog23?s|1( zNwL#moty0|?3!)HCSTKlh2?j9OY4MZsm|p#VPt0dINtj2ps0%LhqkI_^t2ADXt{0i zn5@k8>gx==p5U}#+YFyJ%2??94kH4t|3e-#y$#E3pe5b3qTe39G`Y#Bi^)B?n_i?% zAi@x@xzc9cA5ZBO*9mxzu>;aC|K%B9m@4*>n#u0qn#ghr*k&RRE#)D8Z)FUb!`h92tNm4*+nRpIkERz?06< zRczJ;QXy0QxU`*ZsWYX*Sa=Kfp_Ryp0HIxU;X*X{&@-eNX=Bz3Y5hHrK1AFmO9Q-14vzKUl6YJ^Cw2h8m@2 z5)yGzyMHv_$mnv1%x<><6EG0LfG?PwUkaV0)4*H@BUY_dl zT!x=2>h+J|g|AJ8?xfJm`}^tUVw_1^tJJw}__Q+A_nps1PYS}#v;67`))HfdayR&A zB89cT7)}iE3QreLGdMnPZta{d2@vd$cR3L>XLG8k|E$-rX;4cF?ehHuA$@f-777mjPPW0R9EoXSNU#XV1+FQN4Vu^^iSkKPUKb>Vb2SMqx5N_C znbX#3=i!yP_(u-gFtSJE{^`jNXPP3w?-)J?i$65FsljXZk%DSMO~K62ZNneDp0*}i zbw+MYOrP)|TAX8<{vhTzFlh`?EC*3^ZYnS zgtZp3!@c7Pq&hE$R=&}j>#oE{E`?O2@%nQ}WV1Ni{S>hxKt=ONHv`aH@-ERVq#4=T zKreS}{|^@+->CkpYIb|{qb<@jrZ4vd(}dLaKp7h1eT-r6kepMsMM%6XH~=FZkHzBC zLg&IRS0OEnBg@6l^qp7i8p|xc!blQF|u9apNBD2ho3 zGWw!sF$JQ!_#eAx=kg_TzMM?=!Y3AQ3iSwC?tVm1R}BDv&;hM{Zp}v$>0(fKEHeks ziKzWsx}yz^X(k^d!{p@FWEcV_Ff(TJQ{Z~z_H zCvHPcQnxFJ_yXsNP6JL4#uRNGj{GR9x z&4JIHGobTs#<$->e6D$nBSBVnY1yQ~raL<~5r-jM0 zfa82}L?S_=lioLmGmZU;ioc-50`B-7WhrTRlfkWN3eN1X%?v@@Vqbl5)U3hQdNXo! zCQePi=YK^jSGWPzRZj{=haH_Q^hL|SFI&cSgz@ORlF^n;SoRD+q;WG%-`>P^BKXEPE*c zgzXYtn?K|rFc?>Bv|gfC%<5w5Q9?fo+uaiM$u?h#!zv6|x|Rvgni?2u0LfDYqNX>4 z2lfg{pqs3wu=ie)!l=Mpjh6$Mw@#3mqtC0`x5*8WMkZp_8XuWaN`T6C_~{t!|%UrMM{Nw^=x!{J_tM@$3Xy6qu{;Ab#q>ZyY~hV zwO~)X49@Rz1+&@HjhB7js#ZXq^NMdEusiqGxdj+@qT+36Nnuz;N~OT ztcqGLUJm=)XdpPjbPryKg$sa~&ClR07*@BN&&Lzp zJ!|rmLQmmuLV3$U7I%I8ygu&hUs>KA)%%35!+N@LfT7)u>CpnzMzcVwa)IYRWrg2Z zX)UVBB@>PeEmBXSOoxO3^6z(qvB~)Z<*2fr6Gr=icZcO;EnPr{b+b2Ft_wBr;WDfo zR%nZJs6zmC!rEGd9$Q=P)z#rgQ2sHIr}NofR5c~)({+hC$^JHk4|kU{ZfV8#R5P0% z%GDH8v^aJmtK}K^Hos9J*4=EXKd+jJaPoZ$xQsznxzbaEt)?gfPPo>=V;lRfx7Y|1 zX)StO`L`PLqu-qoK3}NFZP=41>O+hw%jLDf-U~55`ichdPuI9Z$~bv-U(i`3#4QJ$ z#hq;+HtAHj8=VsKqvcpCyT^I3$@i9HhMgM^jM>r_hbXc49u3?%9Jd+Kq~4664vW#1N#jLSFxjdlqJFrQeF-hT?I`f zsx?AequB#Q>eE=Z)y4cjaukE=7*eKWo(K1TZn9+6ZSRX^)I1X@wAOfAGL-b&OIY36 z#yvImmT|&bL7_DvqNeG}xsh0wGYoG_=VH$$xz@{#$-!+gm-a+M`FZQGx}2$iZ>{4( zJYh;5@+yN(p?FdXldNNvd`Cq0=-hQo_}OWY_aRpW*uT%>_Cf!eE|kHA@z&@D)HxMq zk-1evIE8D8`vZ;_$6pG>DIFZ^9{2E5y)s!Y=e^Gbz(b|#Vv(Dfke3>S&{^(oE6P<{ zJhlnX{|0Y2Ho(l})Z{@AfySaUG55q+SVXc6QBw?C7V>Nfzb~)Tem7i`P~BREy=mbj|`7&9?vr|U8>qpOJrNiIm(t*z>~ z?S=H{@#z-a*$jjLN20EutBMudKty5<9Bxl9pTfRzfSR31kEog_`*Y+laP z4G}tkfHj8A?B5!n7<&*iN;~6^MQ^4uC?B)ftJ9?oMk}=UDx}6}&gfq%!!==$lk&pr zOQ0}$asQrI!=q*C6Du3igz4n)m->6^*`~L^dSTRvy4mz$%s%fDHZXhSsL*w{tz7#Jiq#< zZEpsD@v{}fvW&j|@`F|Vh>dwXa|aWjkWpkRTE8g2e%cm&Qxo@(Kb z6DZQ4K3B-~r+VDRtDkKqbhACJhdc%2_jpDK~93%tv-msCKxO`iy1S+@t;usn9EZ>6l5_ z*69P)+wlnyG77%el1Kv}9foe1O@RB})Mk1n>}~cmKSz*^$s92y6L-;u9~9s z-Ox8h90Y*^A}bo)m|i@>$%PEaR4Doez?j8PXXev2_@-%=cBd4i=a&%cC0x-mB^hzK z^WfX;jaXS}Wn&tlAN+mHix=ccV>IezRGCjs`H_{mfEZWPIcN0>ZrSOk*CXvkeZ&0I zxy1~=Lx^AY4-&Sz0*eDbOc}w^T3GtECzoMy6bh|TU7psc?7MYgz^Q0G?RK%ex78x0p2~!Qg?Vk!VhD-BP7V!e z%ZFwpYhD65>P5IY+PBvFI5AOO6hPzq2fo$AE|dkFPTQ5Jo+wlo?N6!3 z#bu%o*4mu#xO1SB4`U;`xaJ1>1(w7T5Uv3uh5Gb!$|}SMS8Oa+Yk9R6o;Wcw%ZZ9tl^xgx!c;8FnTK<7c*X#PF+2yE{&uv$7l0z-A9imHo4(r~ z44f5@Q1Ienx)vSu^xjzM`~WucTYBmL_ace6bINXOz$@RTC1=UIlKb}cDPBR%y?E(k zA5PHM1GrgffF6BCn&}F<=^$Gzu|_l{Oe-n zE9rnP8+CO1z5XA?3K$QqYB;1Q5*aNN&+iha42}XOTJq>9wjnvzO8&~6PXqj&6TNcv zS}r%VU#OV#qdS=>3F!^ZD&zsiG%;ip-0Cz@e!+C;4*1(KzuoW>LM7#p67nb=>Kc{Z z9A5%J-8Q|E1N4z)D=|yRDoYK2NW#4cS>eLaa`~fGhH_ibAR@mdv5vM>yKo(H6-H(l z{f(p|)@Y5jkgLx(NwiI6mstye&D5jD##BT07uzbzb#+ryQ-zwNGm;5ejw6tCtYL#K zUU%BYh?74Ts(5@xak;Kft>#f~D z9rhvzIF2+9yKUHPfMinMJd-JF4!O|MVC1Ln@m&~oN3;{ER6`}6fzpcyQ zP3V$`Wf`M9UHhl#wb7&IH2B?91Jx|3rL_ri6EnvWBosm=B|qZkSoEF}rG3c(F*BhH{}tvmyBYDkmd~GY=GTW5h6*s-3UBwPwLh2uZLo$5A6>kU`O$1+ioGZHJY zP*ch2igpK6Dxvw>roHL`y;Z@378%RzsiZ=btOZTHItuz!TDplGK5P#YR_GA=NWgR6 zc{tbzU5UN?nbR<&1W#vyxi|yQcxcTq>i)BfF48X@l`prVYP<@mL2`5Y9ZhEkVs76k zr4xt23&Etbi(ATC3B%M)EM{6H_jQGbX2bDCCJM!V77KAW5YpSsYj1#7d~#1NH!4|Iyi*k{+o-<1cX&VeIiRbj;~hrgf@0R@1>Wl^ad%~sgJH=f+?bJ(UAeEfh*m^^db-lb zf<4L6&1)varG9dErVOT80S3eI;;Til*deD6)kgnH4)GHkc_+5R%MNAYyo^#u32k9I zlHuipKImv)E~CHsZtRByI2{Q}C3eKJkwA(xetD%%Lac(kwbO}R?boQ}{n`ww#@{4N zN~G{Xz#T8ByiaYoBAJk}$}#&B-XuN52hdmZO1~tSoUQZL7{i$k0r7z|*u(h7^p?Dh z@hOv(1?x@U_5mBiKpe3X7o)3}T5jAj!`#df@F((jC9vHoK4i*71Mj>&2};=*XR?=L z2ncUd=Ipk?8%!ip0M$7PeUKIDS5okNGFbGm0W0nd{d!h;GT%}ZDokI}6iw|kMIiWM zQV2Xle{G2=RF4PxSk6K8!!@4kUJDQJ(t~jX9|y~YW~CMdlGtGw_;}EG0T1DoW$zLj zRmJ+Dgp5S1r0?DnJd53W|98d^sH`??l;uJjNP8t0@0ma#4S7#Hnz0``nJ>fWDQ3TZ zvdOi}v&}EyZ91J-#8}rL$yp5=&5E5lT@p+gGqwCMGdqjZSQm8(;*Ew5Hu4a&XN&2m zXg#mGtl-R(vYs;4hj3B1g)__Wulxbz#N>8yzB`|8#E?T71z3*w()Sa1jmmOmJ=VxO zJQ|_yw>;Jv(*&Ib%>!P)W%hD~e(15`6nB$D8!Mbg(WI1ARK&D=j*}Rod%{F6d5Xu| zc0Z!Ev1!x*LGxaYqVtvUo)s6G$!W>9!9!y5j{uL|JA0TQkeTJr5PGmnMfjwS)x{4T zwv_BN4s#n=?=@=0K|!u?MvkXX^u<;A3wcD~W4(l_&V<9Je+)(%M8=Xt^og-?s6N4Q z6S|Vt7v!Pt#3&=b9X|WnQ7YC9@MlHYGHPOKqjyjEuru9;W%-?A zH}-FU0@r>a|CVZ_NTbGS{AmpI*9U(#Tg+)WCQD63#1Tk(O6zIb-9`cUG1(q$-k0 z{{yC{uy(xui_xo{k*x;)I+q_2Yb~gN+vJHsf4oKBgy-NS_#i8V0g+!Ooy!mS`@b~} zXS;34XTNs@KYvOn+(T>gpY#5mk0qlHt!9t7sC)P*ay_vk+}jk0@RWDE5Yh~EoMDE? zXpioYI%D;M@xo$K*DFa0F3gqdKv-pVJKlqMc%g|hKY_zkygY|=10Am*dWMzmxVy<# zlddjcAX>olA0bkZyPk9$26O16hVw=r85B8>4}6){9|S8$ms}$z#}k6X#dImFoyj=- z?)d@Z3kt@_Z+&?NdvgR{-X18OsULP`>sefzkvy5x1j20cd29EYJ|U>v6ctUZQmKfm zXrS02v2;JQv1}LPFnq`)%AXqknfdj+rwjX`15-i3agQkr8-BrbF18xK*WuYcXb6aU z&BUYF6eb0KLcE$3)Y&MaDJ6wP7j zk!p87y;f$3xQ0Dhq4w#f%CK^Yo<4>G>mU?!I-8DejDJZeV6t9*tBWFZS}ubAZeLtq zXp|4yZs_N=FH-l-sSxE{Db5}tNUlYB&x#{lT7 zx|G$8IDMo?S?XP<`L-_pYhk_x1C_}&g__9e0mqKk zv$})~n|q3}QX`{rIYm{$@v=8!048ZzBk|2+{?e}CzqIQ=XI=(q`QH!pA9p`|qo4ix zIw8V>-vc4)*?m{L9Cl%!UInc9w2;=yoOX~ry=ldjX;x9JVuG-fondseHprjH!Y2>S z2gxKX3pApr$QRH!{#j&98!W7RUb?@A6K#B|@$P3GOQp1*WB%K2S!k~Kky(`@t}g|ao2nqq$^EXb2BkYb9=4tk+v+g z>ByUP-{{j`Wd;eQu(|G@w~kx0q(zEYO2p(4=hP&_Jq9{)EL(2Oqf(=hlq4bewtcdl7R+q;r1V`g4Hz$HIGsJ@6V-0fG z34WgNed60zYc@Qg>R-4;`lgZ^3hca|yL@f5S6U!&Xgc^dYoICT`7n)VyOj}j@mO1T z>3FbYg0^C_8HRe4O`S3O*H-KI5-ZI-Q@}5{BdaV^?mEYN?J|M_haNM;>q(s&4tpy3 z3**0@i#K>uzCUZ)~-+>wQ}6MoLY!v#5iSPpUNw5>#V5L%B)d?Cu~L zDKbPPnW+XH2}A>!s}bX$1jQdjOR8U809tQ;;)RwTG9ub&s zX)!SkoU)#c@mW^)h^CW#8(_5vbpjHM6l z=ns$GqqO)mrWZ!9syVJBak{6w%W(#S8BHg9R>C=ekCe>Uf2OF^?RaGiB*TNEsgA$3 zsagu4D=eyOT8_9~oxr!ry#(<1(OaB>bWBe>F(R*VMQf*V{v9iRRNmyzb!5ZfZxqHzN*yh6oJ{l^f4s?Wz500R#cryl(h>H*8+8Rfv`XvMS0%hr_ zNT0r@mQiV@;^#3;Q1I?>NP8542u}7~5FafhN2|kpG9y*Rz5@y9#U?K!_qYM^l$tA= zIfZ4S>e__UwPD5)iBpLO0U8ie9uYV;E18DG!UC!R)a+dUq{bsNAc_p7R)-H-kmw?= z3|qijiL*P|m%-}-%@t67;nTgo_@jrL_HXv;UFEnk%RiQeLBTYBEevW5;E5^4xJ@Rq zTW59$T0F@_HI|=^1EL05*f)^6{WF=zcJH(?$wENVdICsY#QU^~#C>U>4s1K8{#wI3c#Kh5Y zacERjR5YWm^Bt}5d7$xfDlC(DTml(oODceg2|JS9PcF{iGAxJt`a2bvgP;u3xV%EU z=+<2L%i2qG{8d0j{%?7Y&uG>4KkJ)>?<@6qm6dpv&>TuSIX2$ain!BT4i^iIjp?{8 zj*g9t0sc*GWq`JKBNOSm+0d}C-xDP?MIOiSud!CL*2b8lsmcwJ3^knd7)?dq$DL1i z|FvA4%DsL{BM*H<`D2_L_9(vfk^lHmpc&fOM3tA*%cZgZlA(9CtjGy>@9KT%S27V$*3u z-G4Pje~AC&x87c#-Q3*%7#ZdN8#M)V9>YF;BVX6QJ($r4gJb#a=NmF0Ov1Y zIVUCcJA^Sbw3KR? zyTQ ztQVzD3;a9j0RQ7460!kuq4fk*mC^K}DyRSeAlBcr4^51gI{_3?3)$~sXpHFqP$JQ?G>73;rpbE;QUZ-69<;95_EG#ONSz~ z4)}d1Tj4B?Na{@wC>0#yx+UEZp|)RaV%EXF?IEEKLkMXCLj9P$#qaty9*pk8-QB#f zj7%$v8zFe&TupBf2I@(vt@B%%HLr(oYxWu@mAE#waic4B?6&tjN1;H_@aB3zLO4;Y+!&J{L8c zY+Uo6YV&=UsE0)6)82#D>|nUgzSVk~2qCH%VEhCkT8SWOq16OxQ`u!IJZY$it?@O$ z+{4jZbn}9w7&mybAM=Ixj;gB9(uTTHTw2;u@&l(+fX{P6l*`r2-A?c_0ZgcsMPXTv z_y9_sW0Wk&@td=vH$Bl=@ffNJg`?X#%sH-;q3-5_*ZD`cEnh@J-Q|yg$tae?@`cE! zI`>t7io1EodlrmX@M{jgL3B#5*0$F2iS!usD)%e&F2AezDMKE*!O=ej5Aos8@X)EVD4zt!zghAdpbzJ71? zHUMKCD2xm%nIJ|XD!vbJKh1yi&)(kD8+*;wbiEBp_0de|_(!k!YgcMjfSJ*(F>*b1 z(}3jvN6A-q)zyRBwzRmrL$Qs!dvSM%jk~)SC~7G+~}tELO_ z*RX=A7-EN;&d)2`78j-%)|!6Yg9Qw9SGE4H46zCmx3k-Me8|`;xmNtrhj0Fixj(^! z8(Kfr5?vkN9*>Z|im9Gm^j!2o^mikvD*h7{t>Hzb5bgh2)5bf1bcWO|j%TUodn%BE z`|6Bg9^t;2+F+LAJ-PhqH?jKRJP|ePW4SN^1W0WUuZN$ldPPu5S;j1enN{%4*2@Zs zmQ*b_*iqAJFl?XT)24D*N&Yh`a6Fq1cS_PW>EqkJ+vZR2AQ0yxjTqG^$g|}g(ZQwl zQGhk{+v*~VC~Tbfbb0xr(X&@i%!U)L1AolthRA4lKxnEw%ayk#rj5qAsJTI!Y2a@61rc+YQqa%s5TG+Me*gW%= zT1{xrv~%XajdkcEJIABISSCnLxptSPKM%jAAg;^*RXa!VAdt zv!)Li42sEYW5cAY_xSY+!5MdVo!S*AfLNjAmo>&pswH6dBfQ6|+C3gR=x#2w(=}u| zPu!7VB?j$z9MzmWo&aln^iEaW7RJ=$o5}?ttU=${dI+3){-4lv{KW~BO7-+*cx+=0 zU|%eK*|lz4%xV>!!D=q`LjUN_)Nt&dTwXeS{`Blq`|62gd=V*tJE?vym8DGeq-v?= z>Frwtabu+p6-Xi2f(_L&ZEAHrZ9!YY(Sabq>%LQ#P%tpH|0Xx@_TjzFX=80=a!zSu zZHA-3WjR+e3%E7sgGx9+-`DXMfX^9NZPXzsm5OMw+)N5N!k*J4V(ip$-t+|V?G{W+ z!}0+)rJ7ZY@&xhSDQ*ms7w`27<{R&wuzj~z5|UL!XOe+Lp5{4sO20-}jqfF!?1jBi z$e~r-xQrr6Gy|$TgA;{(K+UcC_FO#--etU}8A90rq5(Jq?re=EY6nWYZ=E;la407| zWG+v%lTWf=iacoWhK4(qgd``zGAXS(UIv%P6#oVSv)BNx$v%BQr~J!o$G0O*^>B0@ zjXIACGYJ#~eDuNHYD-wUi<9wa{Pw^^)l7^qFG!!hc2e zG^NXgtf>C%bgag4Qn)#@DrxSt{$ykhcT=8rsger2_B<_lM+@2yl8n$g?rF@Ix9x{U7jQK9O^Prcrmu&gB4 znXb2TbYc7P;sx_iVW#4`Mtac7A)%2ppMm5(b72!5Vljdx+6>Od$JDH~K`6LACY6dd+8;Cgo;f+XVhc}IfHi*h zl>^AYm$*eOpK@A~1E4eRx>kyP=7cDI0S0wbq6}%VKwHi@w+FjZ99e#Qu*v!gU?ITzyl9bcrGS zm7{%Rr*Kb{6k>{V5dj!1Q~U|F<{4GmWc+Nprab1Pj4`yO$qr564PIdBF@|etr8l2% z#>xlkiI=GpShzgc*Zgk0q@r}FjNGul@trm>*hIakg=Zy7{kafWHRcOHlWbC^W&MXHSQ z;kJKX*Deqjnqz*eJWq+f9WsvC=!%Upb)vm2!Bo$}Jub;FGKq=1OM&EnK~tIy*spty z<=wqC$<#pWU;FCHZNnT_;k-VS*IuqSmUyq?NYs@|BxDcWJ^WeLlkl_0_Z{KOx)J;- zKIOxTZtPXO%b5hG-+aH^pkFRM9a8Ut#b6nB!Wi0IGq(EhKMS=VND?ug<|F=XTQ!cL ziPyJfR)C811N_Tm2jgO$OJc~$-i@d$K)8$4hjPL^#fN&&@ey~nfq^pqbf(-6wmyM) z#MAK_0b5TK#lwc|K4M2rz!}r_GoXZ`3|X>B#QtkZ+{Iyg&p*j=CDksh^xnby0;dBIbYrq z3_>$oc4Iq6b%sJV5E0dFB+3f>H~&N1RbQk@Oa^zO6++t{`c+EV)8UryRQ;)X_X;t; z)%2KqBQ2Itn#>D*Adtv)iC85A3vnbn!&X9HS75XS#u$ruU0CH7BXROg$4>+n*=@Eg z96PB4Yv&voI*!g$y(MOhL`Ntgq(aX!o5$_wz&SXXN%^+Gy2Hxi>9qgV6nf04A3LT+ z?1i82JneeO49~iV*Ek2k#zXK619FMIp2J?Z9hl4ApYl;ZJ|D@SfSoVj=e0i!A%sl8h7bF!(l#SS)kVAVFu zP@b?+ha6d;<9d*$CLIx82oJV++X3E%Tul3&h|n6cIUyj9ojV*bS9@}v`6Qa}Ev_Rj zh_B5ld8ebO&ItTLdHXAl3Bbd)Zv|quN#RZBd-*iq`WG(RnRtE2yKX!A%(kC>>l)-H z`RGJ=;^))hf>H-NbChGJGpV;?e`{@`Sk?WYu4!^LS#4m#C$J39TX0igOg7AU8T@6A zHj8mCz3UR)*!Y9Yn~<32efZ4LWp>(Z30)B{nCe~O8IIWVTjU(;H*52F#3_yrR+5cU zVLwyd!sc&a>X3F52i-5FNJw;TG`?S--~l#Mi-fKViu11$_{vfH*=ip_ZPk%zQr0;7 zI`eqt&G2l-AI>t@v}O+_qo6;=%Usq>E%##CD9*0CE2ie5_RzXej70(muKt{q_-CQu>}ahZ+!=*k{HC?q8z#;oti^geu=#z!>?I{qYGU z-Ai-8z^HyO8s8=M2)`TcAVz7AGIk8;Q`DllyIaOZ40*yktJMP$TsS1~c! zLRWX?>X(z`+MlU62@S06)2=C>uf!F+|GF;%&Nwc_hKv})QcP@HFfCD^5F7zd{)lM` zCYNJ^A_w-X)A5~^T+jO5tVb}qVFJb;ygEj<-(ZLqacA9k;%YmU#p(|Gs^m#_um6GS zaa=+Q$8VjeWz#@1Nd`JSC?N9GZr{f8Nt+3@56gt6sUOU5mgQwvlLyWkcrDB`0v{Ejlf=}`Zf`)U z4HGnQIYY7st~OAfH>qS&QGMQu{BC&7wbuU>=@6X@Q+4H^#xQSOh;-iqbQt4fX*W{o zQlS!xRReBa>|}5-4Q8B`bGTBe6KLw3)kgo0g@E3CSFrs9>yijk4E z-qzcVZ#-Z7u%uj<4TqLKW>k4eunwE7i7!X&&@N$!Vh0@5VYBQSkN1AyGtKNx!jFm^ zU13sPMkz&+s?y~p6xVZc`(%p1n74zo=M1-~eNv9U7-UJw>Tt9jlIVuVsc>QP`j4_6 zze!cI4aFbl;?j|9ouj%SRF${(7 zk562nJnajC4-p)%4<9IYzwP;s(|AD?$?KL^9|S;VJU1SVDpS2+J`Imr4#&4Z@#P5= znjj0Iok@UVhmS|Q{vAAN*~ai^RnJuw2Z!6E8c5-)StDvW5wIcXRO*ON-w8!aR zAdzLv=|Uu;lRUCfLoFEzYkoW6dB%n6ueqKs?V1|@F;AkW?LOGs!d?i9zRoxsA0;JB zVQQv++2MMi0}Uo6o2IZf(0aPE#hMm6T@I=LO19aG?F*T4<(+8*ap)}A7kO<4xm4N+ z@06_u2GVVHw@{h1dY0&RF>60Qkk#S#TvfVGFDk~Mek36J)-C@cCy2kXy-GQfrhunb zuuBJ+?3;m`Utthqp%PEsvvu?(M)o+xb@P9`9B{0e>vvC&W?=2#n4zW!52R5>b9Y+8 z;#aPdbI8LJ#C5w%{THissM z(Z}D>SL+GS?Zz5}Mi0eeDaw2E)}Q`iLkIrFOX+r?WwH^b%X1E5_51<}z6&a`G%zs< z``4tcf(iPl`}aOR%*THL8}F^LD`cv#?&-Rp*H7|+o2!5S;Jyrk|CI3XCzPSwZWBaU zC2@9WqJ3N(*3h>3zRJO9a5^1qQVLS(ly?pjB|Zo>#TG}d?FFLAZz0$d?OXOH7}7Jx zkk|Sh6L5%Q7$4MU?k&y=1LSwNuL+-CD)xN~zfxGcXE#-#wsF`L0v{n=s_f)vPQAo zXZjZWaMGmDuz78UqJ zg4Tz>xpEmPT(#ex5xVGEk2qIB=I=y-TaZBzqNEMT3=+dHesCBe3D{U6fqvMb;L;et z_rQ+Z&5=j3%R&okjG-W;K#3=H9D|^p4DiNJ!lrbWvWwIZ(l}>>+KU$dd2>Z@&Xo8o~<2fXAhQrt)4T- zffOt*&Ho9I+n%0xCg61fS(G4jgFJ?7?Z<&3sbfI zqdQv8QRjAG1fkwWz1oh48g7}h!nL&6J3?2+R}D;>C>vblu0186RAyDI8&TLbJ150}>wn&V!sJiIra+GKF6Qv`+yplfeuVm;lDKrB_b(nTU< z?v6^MiO@DRQB0w@5A!|H$2-d5Rg64Un@81Z&L2uG%&_>~jluT8L~%&U>p4cZE&7Iw z2a8b7#|CdzWwMY&m{)s&IxxwAIY4THONX&&dZUrxF`Ah2&XC+oecocT zlNpl!9{hqh5|`KF^#XIqC`hVK(vvN!wZdU5MGY^)qPK1^zj9x$b1d^qPiJMGUco=? z{%E;zyUTZa=8^Q)Z#{~1X=`$II(qq(u`y5h)qb_s1|Mu0rI>og*pvs6^=8^z=P9`r zM^K;FMFH}gN7J~Ub{F|U>3+c5aF)V790~z}95y#K!`V-oEN~LXd8Wlfm?f7yRZSyC zg2v_iidQ)ARcqxB-9P3ULoPsRQA#V|O_Xb|h@-pC7B}y5#A%62hNne6+}<_mTAJ|3 zoY9q8DtcQ<8;|{Utj`Z9K_}o8AJ28I<(3v*yDCeeC5K!zEP!BdQ9yqCHQZjYU~kh_ zKvpKtZBy$h+PNDjGmz2i-#ob_9OfxCf-BwZ#+xwL-f*2Mm|SS;MB?iiS9uPFs#VP7 zHSK6JU=^Qwoz6B&BdbsFTjZXPiiK2*wLh|d(3o1U_WKE=f+N)(wYn=Wv(ay8-Sg4h zhdqdJzM`5#Qy#IAWZ~U@3I;yr?D#{VxO?NjpS$ZB0pu?%@qaxW=)~h$3c_>m*)oOc zy;w~gXd{$`9qj~ToR#6r+0Z3@E27zMVVR+VK-C@;9r#$ngw%}DRc3cw`gRn5Lo^*t#xQUut7lSr+8=e6nHfYyZz6fwjhXK@&qK^@bQv=EfN4{(lntCU%7Z9=-rV<| z*-ga>L%Pwz`~DF{^y4&2n{+OS%U3x@PpiCwYQlX5FF;oYo7Tn|(NK(42y0o@s^qda4y)0vFEysG+*;LN4_=;e@ZN}XhtT98Eg=DxG~(bi!!$ztw)1bs?ho@@3hrmc+o&1C3jfsJO(0JYyt8@2EvJFRc z(Xg(B#Rh$rH%Sc7IT@D>x>{p1)EN9;GbL+2nQJ(hnC6ha>77e$nd>D*8-W#-gBaa;X=_ngu?Z4z^ zMXt>AVHUYK%Mv>@Medyn?@aO_VM7)>oAKcT9j6gu!C^imUS%c-wlJ;I#~_^ zdf{1E75nX^?lC^a{@VZV7F>GEw`Wq-1dNWfQU!3Dh;5W+ zJkaM^8g9b@xRD>n{|(co=*dhlWvi?2oop(==?uCV&WMry3Q(VJ9t!?6`9&+8KZSSl z40+o)w72=J-=m`*nnP`DNOie zKm<@0CGGOr0LBlqOf?BzliHThV&(!7Wz3Wq6c)zfIy}etI4S=SFBl#UQ)?D=z7_Z! zbfqG`VBURRLRT?`3AP|{OB`g~f<{CA-cwY}~9+5g=?>i6TYNh7x*; zpXq3$aU}CgrN=#H#0m&`53@~0&{FdmS4W!Y{kL@*~IYNBd6WQxnuOA zUJ}FKb=f3o#Ad6>-v<$kTIbvRVc;wwpgAgf{O%cu#6xP1m*c;7tg19A>ahu+eW64z zs&#Z>|7Cox)!~5`CKHa!_KR?R@xu7`_@;(-zt~x!#=WKL&9(8bXuJ?GGpLD-*@g96 z8&dY%oZ^8CLt@3`N2uAPfZ3%0S^9o((rovN>M@z0qaFLV;K-bb1VuhP|E4^8%G;J| zn@(CtaG)q^@5^-M7=J=^jEpl?Y9Z-u)*9Wr%TC$QTM>S(zQUGYz!>Xh`!`-yp8w?n zbld-8ObWD`ZV>Sf)3%7aI)k%@h~B}WI~yC<5*#Di9PGc+Z%M%O+=PF6p<(e8sV*bz zG^Bvh#0-ht54HshvbZ-+8%1CK;9Cfq?dil>{u1voGo0-erV9WVE9 z6sByeuM#qkI=}f{$ZF-)M824KLIityAGLWET?l@7@OxOnm-rsW*w zruC`1yCK%8CN9$>IP_t>S<~oA;@81L{`$&bjNW=RfhWohg3AX=y^w-)5a0c|0W;|D!7yCLyeg>of4J8L7T--`Cf+%5e>lM=iolBc@-zPQnTXJH%ziAA|+J$#>h9(Am%$S$|e zibE0k3nX?%f0no%6YOG5c3xXW9o$#IZ8G2%(N6L!ll$c2m=KS%`gxmQs4~am>S{Yy zP8q0A5=wt1bIrZD_*ZZ%IrhQ;7G@#-7mv7$gG(^JN1;MxoF65u`;ANmKH|PU!53&b zVx8pWVm1*FXQRWMb`msJTbRj~5!fdi;f&jr-137=;Dp^0uTXP;CSXhy3EE?;9ssiS zhA1(-f=Pb78QY||1?_p&5FUQDBj-#RIVkZNDk$@3ZN(f1|g-I>>Uvas+ha{=mbo#%;BUpV+ANKs`dw7oM~Nn{Xh)dIi^XcQrPhMdi? za<05G;ZQgYZUIZwegy{+H;tHs8GpY8xLkjWZ~0^D&1h(97O0ysBM1YeVeW*6SS0E& z`sfcvsHqAK{panw&v?c}%U;1PlPfdTAfi&M`}xRRIH+~J!~ic;W6~{swp2n;LZ^Nv z)5++T#w}BWNy>9fFJaGH!okUDx3iGl4N==LKWk#P+JUB#Xkx2zL0{+q#ZSj#Ht|(E zsM^{hJXQ}+p_jCH&WtNyMe{?Sg;-Oqr*`{X%cD2uD?>-koGid)Q~QrQf6nb)qQ2xo zriH|rnd%29U!z3A(V1{+VPGj2g@ePjL~8?&o;_!&pCw&lTzGvT3Mtacpt52jyjn5S zOucV34?hXYPY>n?f;5ylC!N`Is76AidOXC9gPZ+|jE9hSBO{T#@ACLZ9cz{tb+2aQ zq^tQ@YTXiBQ*WVz9$Ifz^`!;XzW1bQWgEYlw(x^CpUwaelan8ut+q>ciYFU()8@A6 z3}HQyiZ)4bHj zXM0i@WYl`otrl_Da6Fg2mh4;TbxA3@H4#tMn9&+;{hGSR@>VxB&_qqD48wYaPfW7N zy?5kV&o<|11Kh^fQSkwjk$nmtI)j^0{~5I5;hc2H;pj6oC`NIbxDdB1bSjFgeweb{ z!%y`ZLy6ePT;047VbSS|9_cdUc}mZe%8O-Y2*@@}j~=O%eK~QWp1e%&7PLSLRv64< zV$Bme%|tj^k5wLko2bYdtk+dOpu5ihBc|>@gKe(C;wA(`KWJCreP52&Y%d50N;qta z-X&&B{?xcvN=ci|R#Sj_bj!|<{Zog3z+&7ayKLrpE4T{$r+MkR6tynhR0`+|)F*d% zc6rDO7c0z){u`P4?>@tV^RcH+!iQ~_VOzifV3sk+Qs|8sxF17K?~gdk+ zr!(ge0R(2N6u>6ZHwck#4+nS$QkF1}c(Zq$>WG-ZEmmccJ8aVkXLWWfN~Gl`T2EIV z{?t~b`E$X0e}tLe6}t6%^Vgrpb#f%w0=&n80)2NHYz}e$XO8%_!dTS`!P)gxlD>bV zWl)PFsdRpXh zopYpxp%XBHu3H3srLZ{pKwL2*95ZlgY>my8xEt&d0^vqrZz286O=EB4#MPu$<; z#)QIld8K21wdV3TudF?i>|c4f!#|L{H^Q=j;~F*<72uk93$5dF;|&NSTn7m@@?&}F zA9Oz5fIgl%A!XW+`{er2a67bBCrZrJ&fk8+0DbPlzF`y746kW^oN|a=mL;;9R4P`# zuK5_DDIaaNYO8-mpT8X?`BDBN4}?Dy*Cd~?wVj#;ue2t^k%Mq0O_qajz@pOme+!cu zYb8U4Nkr(d$l`~E@}mk1p`1#-v&&`BeM{F>lq4M%rNP`#5)l!Bmy>f9rHYXv4>5(S zZ)gBBkdnv8P$%W)6a)-VGU%g*-M7yc7OJbK&gk31;hT;tG=bhbL}@VSltolTR1Cxw zCzIqz$XG=pBvoWup2oduuVO;krmzO1-pCU5o_t9YRciBGaT$BMNT@iSCxybUnvNJaf;nGyJu5t+) zd5Ka*2^pDgrc-;ClJ7O5VL%26IeP1Mwz*BgB=sMt=A^MhKj}}sbG9NdT*WWP%7YSbX5kjR&Cf2-0 zmRA)LO)9JM63IgLU_kJ+(%Vn>4oAjN%gcL9(qs~Bs_b#bFd+pj97J6uBX((_T!&JEyb7`{I$J#A4`a=<>gg+N+QdtpF?O`9c(av6WMUd2Vs*CN~ zpIXx~rz7dbEUavO?W^W|wl{aZY@cX2%ihXfEg$a+pkH)Oz-WvW4~`(hMDl9)Oe7`wms zgLc^!B|?Kx`x{REdp3fl3t-;w-#Pay>mD5}H3HTEm+Dq;SS3yoV~~Pt=T}sXS)C&K ztEHNUzFj8+O(7*O4_)FvD0IhW_>-wLxRA#`RY3a1-WI>*o_r*WZEeiraAdVhRUIT! zr$6@o9M@OB-uzipj{qz5DncE%n4r!sb6^1!jf!nyLK6NRT3w0(p-+&eI>bB(wr3g; ztPc}rTHKzJfN6>SwxZhG_rqM7+Sj5$t*7KuYZL|L?C2oA$s;~hD!LG}i^qCT5KVvn zoDv0P;Qpz>p;F-2@NbTJ=QkHtiDBTB&{f7KB`3(}dCWpBkDNza>(Ra}GYkDI2sja0 zy?7?z9X)|Ks?wSrWTgRiMk;} zbXzLqV674uV#wTcKLQntMZw4@ib>rlq2POrnvb9J$gLQvet3!9e|I^lZ7iivQz_JV z?}!ZzI)$M~ARk8pk_npcVgPDk%0=nyCsy40rc8sMQ&X!{yt;GEWqH%nmx#yW=pVMX zD<3md;};Zw=y6nBOJkGY2-yPH;S`XRXtFV;;&BUp6%76hOc%DXA+R)>;;iW&6IIZP zV&&&fTIy59uxj0_Ws=Zu9=IJ0zVAv@%#;GU5U|*ykICKpUd?epN*S7`bWw#U^Ha`L zcujv`wS5%38#3SWy&&o+tSdqFG}Kee`>zd*Y;n!s?vnjTw;G@*aDF*Jw+rejERcgO zO{jjc6N=mn8iPy;3Z){zBy7X0BoF+P1W2Gw2>#{mjkvc0-_POD6wSz07cQw>r~@u&dg09-JLQAHXv9m1 zJU`#@&5FxCQon zXs}QG)b(GGocuUhK2+2Vld*|#6^`DM`9h_C!W6Ph%_~C<9>ejL5M8ZuKf3w|DOm^r5hN5)XT>Dtx@)nvY%X3e#rIadeLW57C+x^dn5h$B zZEM4o--1mT&?y~Uj!ghnowC!Ve}M>5gXacAl*4=n6J|WCp0gh6Ux*0HvORn=K{}Pw zt)?PypncN!XUG9W;&Hk2!teHa!t?qDW1TK@L0nh`gmSWKE7P1MxcTOi3E>X&x0@u{ z^?7(FBQj27k#%Rq4(|P3mJ%QAEFYH!>i2KGB-t@>7>|L1Zp2$N?}sKwM~eCKtgUlp zp(Rmx3KMqSybhSF(ZJlF=L~Em26DPO&@=XS#`AE3@`HN?w&8$;DjN~(K?aN|S@OF+ z=7;pQznXEOrX|`-jW$A|?NB4BJ5EvnRL+Uo!!6HDO7a|Q?Wm*-ZDsoCl=n3CYMPrxt9$-z z$q%D!rK3cJ1>01cYq|nRP)WERQo#?S(6*Mo;Tfi3f%v$hA>u8@J!vpd8()%|E^D*>L# zVsvXBzs-XDnsF=9B!jxUqJD>seYg&(5r&aXvKkGk+L_^~l*V9!6zrV=JD9e>WTwRy zEZ8CrR#P<;-Y6iTN{&-ojY=wJ!jbP z*7@qBL5K4N5vnzRPk6p!o1BR}veDzqW4ZG3ACR~Eqzn&`t*$(Ec7gnh55ZKczfjat z4&?9^vqi;PUCza&M%{gClyb@}IJ==UAPTAC@{dZaukXNevZoD2QFaK}mlVb^B->KL zIDZkLYJInH!cvca$oTYM;O3>&yaQg$3iqbx4-EI0%r=^RB>EP#B|eB=xEL;sw~`9IHu z`Pkd1D+sShJ;{LU;FJqRbx)CG+4PZvnuZjQ!M_du@Fhx9zmL-Jj}}+4@ip|t?~8v& z@rVL9g+IOu%;BGh7ggX2^m?Nas3qNxnyGMS!GeYvVSR`c8k8}oNaE!(*{>sQq^5G0 z6B$W0}mE+K_i#ge*y4RW6u( zHUR{*`}@NsVq8cFxi2xxvX`qk-{epyD+$c@46x%)Qz*rmXzdy58xPVy_~6XP3zUO8tOeMOE=BsQvH8tIOWJ@r}mqxa+0qH1XT|ACP4{ zZ>Xq>vCq+5G+jZmaQQO`GjTI0qZ`%UFOm?#8mD$($RbkB9E8v7R6+@`ZBf4%AHgYMp?@W|ws)<66X4pwdswYIG@lY@;FbVV_wVu-rrX~K$3AOu{9A)E=A4RXiwRhKqmB0h59{KvQgn>Y!&&ym7P<4>^Ky}GsF_F z$yyGeo#Cmmn#KrAGn3;3(Z$#Asj^TU1Cc=f8r>p*vt{wu9c^hA_q$gA$$#wiG?xB& zaG4oep|?}RY^gp((Fa*=zYlLs7!)FVChPEJh&7CjhfGG&Of~RShdf+;Xvrj?uGr{9 z1F>WC56VIpMH#)=%EJ5~stBjSIw{{0<2EBc!($h&u-dl|jITj_kviB44p(!;Yi+-> ziW6k@Hair&Hq5?Xeo&e)m_OEcHq-Mf>;nj?EaEyc)Tv^m>r19{pc~|fnaWQ+PF{$+ zJ1mtpCQV)>Og6|;CN{nzSgS!HnzVOzff(ko44aH8D#u5%gCejsns(Mq(GVdZSvU>P zQJ@$4=12|p5k_#{Lsj9R4f7cuM@cmpuiAb>}9_WQD_ zYPyI_^oC*eS`h!J2ucQ~3Q0>tv4A4-p*b~MO`u3}jMlKrO%%&^Oz3x2qv8BFvA=$@ zWIByMh%GCB2rmtLdgM`=N=zQ8O)rjZ-7FLkcQK}!y6lg<`XqJyC2 z=*!$t=YDV*|JEA zT6Xn4V;IPAa8W6>B>yX9^W}?n^5pHZOYhL_sD-UyFiXJUwqWPCfl@EkkLgRT`Sa*M zpBuz4A@<33Z)oeTb{av?BQiA2ZC6nM`)1CZ?*2?+%JtMw@}M=45csogyR3%rbnx!t zej2rOj@l%joIHDKP6E|C($MFOJIfyC)n}dBs4$w1EJ&j&u4XI?A2BviHy&@twGGcY z*+YeWb5I7EHhTHvdZPUYcG5%MU@mX-1fq%NDUC%5b%>7(+@ya%i-s>b@8R8mu+B?t z26uiSp}E7yKR#N)!0|fZP(@aQW^5tg2B3?`dfV0baygcHM4RS-$MT2NE?8@>1Gw<< zDrvRS#(QfSBK+<^)EcNB{>WUb#XOfUb$0F8PkS`)PU$Rl1OEnGt;=Tzta`+Z@jV2-)YJmk}}4SEPrpgH;?K*F{5lkW?AX#DI6kMy@n<4#I+Tk@GF6EOCV@@>ALB_*SYk zVrhEoRJVFoD~qw7hAjGeX6@nV!8_v?+I4Wxt_{u3yEq!TH_Y7K(GT;tIkAM};EM^M z1DLYfzJ@aIkGx`|DRim^)z>&KqD|!9b|a0ykCxqSur6A8q`qEB{tOduv6`tw>?2C$ zy6&wSvWkU;9lC4>x-41#Qhn-Bh`3@-!$>X`%AovYjpZg^*3a6)csaIe6C}f`($efq zf0#)ThvS+$->E^h+{7yvuC3hYYptzHJDyfX!o}q|YqjFVcP8DXGJW|F_1p}dIk?iw z23dX=I}qsn5Y5`oupA>M;A~;^el0e>IH@$BO!M7W;QJ@?a~rv=z*xgZpQ-Ztezob6 z9%#aUqh=}1pJ$%#XBG8o!#IK$?&0c4h>l&67ZxuVkY+-GHd+88xIZ0@t7egXbSf&} zVp1OpjrJOAbj4qG*-E(KFN1h4UTEda(4OyCR)BYO;xk8jsr5KlGTO8-QqRHb@IuVC zO*9%Ye!N?9Q1@0az5RsNG~Bwa!)OyXWaPrTnu3+kAE#aVa9ZaWBA}dhGKma-sWy^#!f@WXPWkbS!lIfTuh<*h_vpOntr^uX*4HX1=jDAXq$MLsY$ z8*x^TCLU-ltD(XGnV8X_SX$;(6pF8JpyRA|01m%NuzLBRb*^eC3VyU{oSBgaIs1O- zsh9Ik#6NLic=04y+bDDq5tbeK^HMMGdq-VG<1}-q1O=jS_RZWT{wcQH$cPGyy>JFp9JuT(n}Ol$_jqhS!b# zW3VKmt80UMx_ICR&2TXm?e`l)UpIkh!AZN*%rwssGt6P2XBs#1KxkM{oc6-H-D zCyGiYv&lgN3j=*m_1pG~IJ+yNDQbH3@N-Gciw-;_ONlCX=cSNzbxF&wQ9uli3LVfT+eDX0CNiKNAzge~AgJw_I8Iv-uSh;?s>x|8pbS=t^nM|C*mwHOdn`%4bbx z&pbv$q4wES{QUd>*x7}Bi4I^`$uVR;f~k(_i5^vvy5hfaUIzb{M!J|kOxduk!YRoC zxuz-jWV(@b9eTk#$J}X4?TxaTd!pcIAnMELmuzLx|3Av*|5xf``f7jAtvollTXIyz zaZFL7hcij!j6^bSu}4uVIAJYLqcz0D*dkU-;hWDt1Od^3%ppNQBbVBiwXc_ zO0)f%3a?c>dvKtXgans4*SqQ2i4{}Ygv5U{LoqPy{bCkJM@HFsdF7}KYkl`eV_xDB z5Ba&T%zWC~c?H%X{*58^32Yd6JV&RNB+5g>k}?$N^a%AN{1k*WK>xxlf(DUzgC7{+{lvkG#kvyQC~wGF4vtF9PAWZ!QgN z0y?w&(0?`O1OGGs$JhV15%SNEj5drxK7$1=4f&G?gVXkl6jOBfw~Pz~Cw-CgoH`sM z9kj@Z?{>tiQd40D3~S+}V!DK7X6KIXPB~Jzw4@J=CR-6dD%U*&9XH_iCXFT6zrurN zv;%NODA83)1aH@DnTI^&hHMxY%v8-JgV;Ep&JP|=F~T^{CZ1rw6)P`^W(z3iUe=DA z6X8b*?nIKuF7>&vA;?lG6(Yl{Bju*pE$Hs}3G5VyBj9s=gKx{kh!hxIxu^7?;4E}1 z>-2~^k!<1nD?Rf$hl8Ue_Hx+e@m^78kodsd@j;k3Hm~#^^Y1`!SwhxK{Fethoh5YE zoPg%C2)wQSQ;3X|)Ai_ICq0A*sB}(_+rHBRvX5thW_^$lJ{q;J2O@J6C7P-hL3MTT zk!2V^br3(_dNEtf(Ts4pklyz2aHL1%KB@|eFKdWD_Ik_u9#WUg=mvE&{ujsmLJi+S z6C|Sn9xp!%ZDo2ty4AHY7NA+U36CbGVkFI=s{S>GKp{UqZF7uZD~&%a&C`XEa>R9b zyWey-L*c7GDeK)O=z0fSKOkny2KT#ErX{!cTdOcHimdUp-Lwu+sgECpD80ZZH9wla zO&4K|Y6QNxY8y~^kFD^(R@*Rv*gN@|$3w_WyadhC)dySj6~amcjR*1k9*PnMR;>XK zjRnjer-jU4&&QG}j~8kMn@n1$v^z;7ZD?{O+s8^VDT|Nzf`3j{rdSNrnE%1oTP0Gg zizICLpPKGGp6Nf119-GTuC#LB%`I{tn?=an>PIX$k)wv@7Dmn`D~Xw!b0L~y=Dx4; zAU8wqGBU~;3cuB_-{8d_~?Am2m`dS7P3QZ>dp z|22IeeOICnEh3KRSefxYK8LMvEw_{O;%yAywCqKb@RnY&hg!s`b5u+BQ$Qy3gyk%|ExkAHlbXk+sx zK=8Ono;eT2e3fIa>Mg?Vm7AoA58G)A&HiFhW{Wt~Nlh*lXmPHWF^J$H?nG(@)$74S zJIw|~6WIg+fUMh_1MLI3ff2-@y6$0%`ffvYaDZlpFu|jQqN|)9~EjklQwrNS|W7R8T{TN%Gkfei!83F za-A%`bz=sBWK747WwPZ?8sZ?tF z5BY%MPct#=EwoU^8DHh^Ci^I@L-Sj_`~rKsl^}=2qRT2eeBY?TdApm}8@d$r{7e9Y zNW5s+z5`T)KYk+1wgw?$k~02`=3MmzJ4~iUPhnnEA>_mN*_Ngw3W}yG+REpzUD&TR z3@vOhe;*e$!cBAkMDagRnC(d5J2{XMkJ{8fAM^8;ZriUW;hFkMBsxKM<`EWcl%P*4jCX=0 zz8XX{WXe;oFV3dEQ=b;8?(7*sZIH_FBDX@Q1kpPZjN-W<1{S1*o=Fz? ztXG5aJQd8RA(`OnJ6>?82Y^dfh8`03vB6f9{0-~$SJ{#|$wt~IUJW0>^y8|ikev`D7PFmq zSQvEo48N%nyVXcKQq)a(c=ziDqKlg?)z357U%9|t8Lrmz`V{QCrBgVw1vH1NE`({A zX-Bsp4`=Db>UN_yq$7@9GQeFy4%n{LW7?%C&V)I^Gt@?2;BDsN1YhJRd!g$>7S67g zQmL@rnoUyAsd%M@WZ44ONPj66_xEFkVP~fnL;CTDkMk=5{r>YU?7k_@a-H6e;xX%o z1J@rW^oYRDyfC{>=AX}A2%YJQO?X{;8&oC^DM%Ygzb*MgjX>+wgFqVR;|!Xaejj>VM5PeQu8XxOD1PmJF+Nd<9Z>o~U+YYE^My7)RT>HZh@+d9({8AQVeE-Z;BqXV?E;fMY;~UP5Yxxp zW(J?&df{Fcz#+3s!7K$tm-wb z$9Ts0=aV*mox4I(b1pXRPq*8xvwn1Y!2C%3vhNSS>sVOZEvz4?p60)Vp|M&DFMMBF zrGV=T!n9d3!&oR5_9+opOi5N&8*8?-@F1`RnSq9RIp#U@Yg}vV@&mlj=l4Zns>N9@ zKVnt-?Lv+SQs@M21w7>1QjxR&n>zmXRBkq8KtX0$qO*Fh_x>jP$H;Byw=YifEZrMy zk%cAKg!bV~VN%seQi2X)WJ{hXd}DcODd@){W*_u}ZRgA>PwweGY9+_^JJmdIFm5vK z!O#%2;L&uFeQNzIQG5l%oTU2*6<6!P!bwKu<71=aFMF9Qtd5s;ZhRnmksofB7O`-` z&GCcsLqMwASY2&jzg=_viS^cu^qEH}=3*<|Hi!7Vq3vnW0a#}h5M*GmImSdS9v?Jv z79y664p(l$xa0TcUEGH}!Q+#1B1)rST#{RE$#6;??hvt@`r;vTQp-shQP(3~j{3lZ zn=#jXWYL<@8<0+dnzWUEdrOk=(oJkO$#2r4vCrtb{k54AMpAFtJMuE6BD(GY{cSYR zHDo-uBpaLQY4{uTg45lTmaZ)>%J{o-#p%=VLaS-z|CXoQ!`MWK>ny|XvU*DIA3aBa z|L+XCD?o%)<|NebDu&T}H2gkP_Se#;bi>nb82y(9um*{`62(KkZ~k?<1l{t+B^Ups zi!#cddve*9t3g%nuX}zwqi}@lPx@Jg3oI~fDYFyq!e4vPEoXY;>woDISTJ|IYB?hh870It1hws0v~(@bN~PV diff --git a/docs/interfaces/lite/pics/withdraw.png b/docs/interfaces/lite/pics/withdraw.png deleted file mode 100644 index 2249b5e34839c9387e4188e14d39855993a75ff4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20935 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 ZbfkgttAP#bllBJi_<08$sPYO+`xnx4A^QLT diff --git a/docs/interfaces/lite/readme.md b/docs/interfaces/lite/readme.md deleted file mode 100644 index e31ccd0752e5..000000000000 --- a/docs/interfaces/lite/readme.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -parent: - order: false ---- - -# Light Client Overview - -**See the Cosmos SDK Light Client RPC documentation [here](https://cosmos.network/rpc/)** - -## Introduction - -A light client allows clients, such as mobile phones, to receive proofs of the state of the -blockchain from any full node. Light clients do not have to trust any full node, since they are able -to verify any proof they receive. - -A light client can provide the same security as a full node with minimal requirements for -bandwidth, computing and storage resource. It can also provide modular functionality -according to users' configuration. These features allow developers to build secure, efficient, -and usable mobile apps, websites, and other applications without deploying or -maintaining any full blockchain nodes. - -### What is a Light Client? - -The Cosmos SDK Light Client (Gaia-lite) is split into two separate components. The first component is generic for -any Tendermint-based application. It handles the security and connectivity aspects of following the header -chain and verify proofs from full nodes against a locally trusted validator set. Furthermore, it exposes the same -API as any Tendermint Core node. The second component is specific for the Cosmos Hub (`gaiad`). It works as a query -endpoint and exposes the application specific functionality, which can be arbitrary. All queries against the -application state must go through the query endpoint. The advantage of the query endpoint is that it can verify -the proofs that the application returns. - -### High-Level Architecture - -An application developer that wants to build a third party client application for the Cosmos Hub (or any -other zone) should build it against its canonical API. That API is a combination of multiple parts. -All zones have to expose ICS0 (TendermintAPI). Beyond that any zone is free to choose any -combination of module APIs, depending on which modules the state machine uses. The Cosmos Hub will -initially support [ICS0](https://cosmos.network/rpc/#/ICS0) (TendermintAPI), [ICS1](https://cosmos.network/rpc/#/ICS1) (KeyAPI), [ICS20](https://cosmos.network/rpc/#/ICS20) (TokenAPI), [ICS21](https://cosmos.network/rpc/#/ICS21) (StakingAPI), -[ICS22](https://cosmos.network/rpc/#/ICS22) (GovernanceAPI) and [ICS23](https://cosmos.network/rpc/#/ICS23) (SlashingAPI). - -![high-level](./pics/high-level.png) - -All applications are expected to run only against Gaia-lite. Gaia-lite is the only piece of software -that offers stability guarantees around the zone API. - -### Comparison - -A full node of ABCI is different from a light client in the following ways: - -|| Full Node | Gaia-lite | Description| -|-| ------------- | ----- | -------------- | -| Execute and verify transactions|Yes|No|A full node will execute and verify all transactions while Gaia-lite won't.| -| Verify and save blocks|Yes|No|A full node will verify and save all blocks while Gaia-lite won't.| -| Consensus participation|Yes|No|Only when a full node is a validator will it participate in consensus. Lite nodes never participate in consensus.| -| Bandwidth cost|High|Low|A full node will receive all blocks. If bandwidth is limited, it will fall behind the main network. What's more, if it happens to be a validator, it will slow down the consensus process. Light clients require little bandwidth, only when serving local requests.| -| Computing resources|High|Low|A full node will execute all transactions and verify all blocks, which requires considerable computing resources.| -| Storage resources|High|Low|A full node will save all blocks and ABCI states. Gaia-lite just saves validator sets and some checkpoints.| -| Power consumption|High|Low|Full nodes must be deployed on machines which have high performance and will be running all the time. Gaia-lite can be deployed on the same machines as users' applications, or on independent machines but with lower performance. Light clients can be shut down anytime when necessary. Gaia-lite consumes very little power, so even mobile devices can meet the power requirements.| -| Provide APIs|All cosmos APIs|Modular APIs|A full node supports all Cosmos APIs. Gaia-lite provides modular APIs according to users' configuration.| -| Secuity level| High|High|A full node will verify all transactions and blocks by itself. A light client can't do this, but it can query data from other full nodes and verify the data independently. Therefore, both full nodes and light clients don't need to trust any third nodes and can achieve high security.| - -According to the above table, Gaia-lite can meet many users' functionality and security requirements, but require little bandwidth, computing, storage, and power. - -## Achieving Security - -### Trusted Validator Set - -The base design philosophy of Gaia-lite follows two rules: - -1. **Doesn't trust any blockchain nodes, including validator nodes and other full nodes** -2. **Only trusts the whole validator set** - -The original trusted validator set should be prepositioned into its trust store. Usually this -validator set comes from a genesis file. During runtime, if Gaia-lite detects a different validator set, -it will verify it and save the new validated validator set to the trust store. - -![validator-set-change](./pics/validatorSetChange.png) - -### Trust Propagation - -From the above section, we come to know how to get a trusted validator set and how lcd keeps track of -validator set evolution. The validator set is the foundation of trust, and the trust can propagate to -other blockchain data, such as blocks and transactions. The propagation architecture is shown as - -follows: - -![change-process](./pics/trustPropagate.png) - -In general, with a trusted validator set, a light client can verify each block commit which contains all pre-commit -data and block header data. Then the block hash, data hash and appHash are trusted. Based on this -and merkle proof, all transactions data and ABCI states can be verified too. diff --git a/docs/interfaces/lite/specification.md b/docs/interfaces/lite/specification.md deleted file mode 100644 index 4ce849acaa1d..000000000000 --- a/docs/interfaces/lite/specification.md +++ /dev/null @@ -1,209 +0,0 @@ -# Specifications - -This specification describes how to implement the LCD. LCD supports modular APIs. Currently, only -ICS0 (TendermintAPI), ICS1 (Key API) and ICS20 (Token API) are supported. Later, if necessary, more -APIs can be included. - -## Build and Verify Proof of ABCI States - -As we all know, storage of cosmos-sdk based application contains multi-substores. Each substore is -implemented by a IAVL store. These substores are organized by simple Merkle tree. To build the tree, -we need to extract name, height and store root hash from these substores to build a set of simple -Merkle leaf nodes, then calculate hash from leaf nodes to root. The root hash of the simple Merkle -tree is the AppHash which will be included in block header. - -![Simple Merkle Tree](./pics/simpleMerkleTree.png) - -As we have discussed in LCD trust-propagation, -the AppHash can be verified by checking voting power against a trusted validator set. Here we just -need to build proof from ABCI state to AppHash. The proof contains two parts: - -* IAVL proof -* Substore to AppHash proof - -### IAVL Proof - -The proof has two types: existence proof and absence proof. If the query key exists in the IAVL -store, then it returns key-value and its existence proof. On the other hand, if the key doesn't -exist, then it only returns absence proof which can demonstrate the key definitely doesn't exist. - -### IAVL Existence Proof - -```go -type CommitID struct { - Version int64 - Hash []byte -} - -type storeCore struct { - CommitID CommitID -} - -type MultiStoreCommitID struct { - Name string - Core storeCore -} - -type proofInnerNode struct { - Height int8 - Size int64 - Version int64 - Left []byte - Right []byte -} - -type KeyExistsProof struct { - MultiStoreCommitInfo []MultiStoreCommitID //All substore commitIDs - StoreName string //Current substore name - Height int64 //The commit height of current substore - RootHash cmn.HexBytes //The root hash of this IAVL tree - Version int64 //The version of the key-value in this IAVL tree - InnerNodes []proofInnerNode //The path from to root node to key-value leaf node -} -``` - -The data structure of exist proof is shown as above. The process to build and verify existence proof -is shown as follows: - -![Exist Proof](./pics/existProof.png) - -Steps to build proof: - -* Access the IAVL tree from the root node. -* Record the visited nodes in InnerNodes, -* Once the target leaf node is found, assign leaf node version to proof version -* Assign the current IAVL tree height to proof height -* Assign the current IAVL tree rootHash to proof rootHash -* Assign the current substore name to proof StoreName -* Read multistore commitInfo from db by height and assign it to proof StoreCommitInfo - -Steps to verify proof: - -* Build leaf node with key, value and proof version. -* Calculate leaf node hash -* Assign the hash to the first innerNode's rightHash, then calculate first innerNode hash -* Propagate the hash calculation process. If prior innerNode is the left child of next innerNode, then assign the prior innerNode hash to the left hash of next innerNode. Otherwise, assign the prior innerNode hash to the right hash of next innerNode. -* The hash of last innerNode should be equal to the rootHash of this proof. Otherwise, the proof is invalid. - -### IAVL Absence Proof - -As we all know, all IAVL leaf nodes are sorted by the key of each leaf nodes. So we can calculate -the position of the target key in the whole key set of this IAVL tree. As shown below, we can find -out the left key and the right key. If we can demonstrate that both left key and right key -definitely exist, and they are adjacent nodes. Thus the target key definitely doesn't exist. - -![Absence Proof1](./pics/absence1.png) - -If the target key is larger than the right most leaf node or less than the left most key, then the -target key definitely doesn't exist. - -![Absence Proof2](./pics/absence2.png)![Absence Proof3](./pics/absence3.png) - -```go -type proofLeafNode struct { - KeyBytes cmn.HexBytes - ValueBytes cmn.HexBytes - Version int64 -} - -type pathWithNode struct { - InnerNodes []proofInnerNode - Node proofLeafNode -} - -type KeyAbsentProof struct { - MultiStoreCommitInfo []MultiStoreCommitID - StoreName string - Height int64 - RootHash cmn.HexBytes - Left *pathWithNode // Proof the left key exist - Right *pathWithNode //Proof the right key exist -} -``` - -The above is the data structure of absence proof. Steps to build proof: - -* Access the IAVL tree from the root node. -* Get the deserved index(Marked as INDEX) of the key in whole key set. -* If the returned index equals to 0, the right index should be 0 and left node doesn't exist -* If the returned index equals to the size of the whole key set, the left node index should be INDEX-1 and the right node doesn't exist. -* Otherwise, the right node index should be INDEX and the left node index should be INDEX-1 -* Assign the current IAVL tree height to proof height -* Assign the current IAVL tree rootHash to proof rootHash -* Assign the current substore name to proof StoreName -* Read multistore commitInfo from db by height and assign it to proof StoreCommitInfo - -Steps to verify proof: - -* If only right node exist, verify its exist proof and verify if it is the left most node -* If only left node exist, verify its exist proof and verify if it is the right most node. -* If both right node and left node exist, verify if they are adjacent. - -### Substores to AppHash Proof - -After verify the IAVL proof, then we can start to verify substore proof against AppHash. Firstly, -iterate MultiStoreCommitInfo and find the substore commitID by proof StoreName. Verify if yhe Hash -in commitID equals to proof RootHash. If not, the proof is invalid. Then sort the substore -commitInfo array by the hash of substore name. Finally, build the simple Merkle tree with all -substore commitInfo array and verify if the Merkle root hash equal to appHash. - -![substore proof](./pics/substoreProof.png) - -```go -func SimpleHashFromTwoHashes(left []byte, right []byte) []byte { - var hasher = ripemd160.New() - - err := encodeByteSlice(hasher, left) - if err != nil { - panic(err) - } - - err = encodeByteSlice(hasher, right) - if err != nil { - panic(err) - } - - return hasher.Sum(nil) -} - -func SimpleHashFromHashes(hashes [][]byte) []byte { - // Recursive impl. - switch len(hashes) { - case 0: - return nil - case 1: - return hashes[0] - default: - left := SimpleHashFromHashes(hashes[:(len(hashes)+1)/2]) - right := SimpleHashFromHashes(hashes[(len(hashes)+1)/2:]) - return SimpleHashFromTwoHashes(left, right) - } -} -``` - -## Verify block header against validator set - -Above sections refer appHash frequently. But where does the trusted appHash come from? Actually, -the appHash exist in block header, next we need to verify blocks header at specific height against -LCD trusted validator set. The validation flow is shown as follows: - -![commit verification](./pics/commitValidation.png) - -When the trusted validator set doesn't match the block header, we need to try to update our -validator set to the height of this block. LCD has a rule that each validator set change should not -affect more than 1/3 voting power. Compare with the trusted validator set, if the voting power of -target validator set changes more than 1/3. We have to verify if there are hidden validator set -changes before the target validator set. Only when all validator set changes obey this rule, can our -validator set update be accomplished. - -For instance: - -![Update validator set to height](./pics/updateValidatorToHeight.png) - -* Update to 10000, tooMuchChangeErr -* Update to 5050, tooMuchChangeErr -* Update to 2575, Success -* Update to 5050, Success -* Update to 10000,tooMuchChangeErr -* Update to 7525, Success -* Update to 10000, Success diff --git a/docs/interfaces/query-lifecycle.md b/docs/interfaces/query-lifecycle.md deleted file mode 100644 index ae4a2e800b50..000000000000 --- a/docs/interfaces/query-lifecycle.md +++ /dev/null @@ -1,162 +0,0 @@ - - -# Query Lifecycle - -This document describes the lifecycle of a query in a SDK application, from the user interface to application stores and back. The query will be referred to as `Query`. {synopsis} - -## Pre-requisite Readings - -* [Introduction to Interfaces](./interfaces-intro.md) {prereq} - -## Query Creation - -A [**query**](../building-modules/messages-and-queries.md#queries) is a request for information made by end-users of applications through an interface and processed by a full-node. Users can query information about the network, the application itself, and application state directly from the application's stores or modules. Note that queries are different from [transactions](../core/transactions.md) (view the lifecycle [here](../basics/tx-lifecycle.md)), particularly in that they do not require consensus to be processed (as they do not trigger state-transitions); they can be fully handled by one full-node. - -For the purpose of explaining the query lifecycle, let's say `Query` is requesting a list of delegations made by a certain delegator address in the application called `app`. As to be expected, the [`staking`](https://github.com/cosmos/cosmos-sdk/tree/master/x/staking/spec) module handles this query. But first, there are a few ways `Query` can be created by users. - -### CLI - -The main interface for an application is the command-line interface. Users connect to a full-node and run the CLI directly from their machines - the CLI interacts directly with the full-node. To create `Query` from their terminal, users type the following command: - -```bash -appcli query staking delegations -``` - -This query command was defined by the [`staking`](https://github.com/cosmos/cosmos-sdk/tree/master/x/staking/spec) module developer and added to the list of subcommands by the application developer when creating the CLI. The code for this particular command is the following: - -+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/x/staking/client/cli/query.go#L250-L293 - -Note that the general format is as follows: - -```bash -appcli query [moduleName] [command] --flag -``` - -To provide values such as `--node` (the full-node the CLI connects to), the user can use the `config` command to set themn or provide them as flags. - -The CLI understands a specific set of commands, defined in a hierarchical structure by the application developer: from the [root command](./cli.md#root-command) (`appcli`), the type of command (`query`), the module that contains the command (`staking`), and command itself (`delegations`). Thus, the CLI knows exactly which module handles this command and directly passes the call there. - -### REST - -Another interface through which users can make queries is through HTTP Requests to a [REST server](./rest.md#rest-server). The REST server contains, among other things, a [`Context`](#context) and [mux](./rest.md#gorilla-mux) router. The request looks like this: - -```bash -GET http://localhost:{PORT}/staking/delegators/{delegatorAddr}/delegations -``` - -To provide values such as `--node` (the full-node the CLI connects to) that are required by [`baseReq`](../building-modules/module-interfaces.md#basereq), the user must configure their local REST server with the values or provide them in the request body. - -The router automatically routes the `Query` HTTP request to the staking module `delegatorDelegationsHandlerFn()` function. - -+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/x/staking/client/rest/query.go#L103-L106 - -Since this function is defined within the module and thus has no inherent knowledge of the application `Query` belongs to, it takes in the application `codec` and `Context` as parameters. - -To summarize, when users interact with the interfaces, they create a CLI command or HTTP request. `Query` now exists in one of these two forms, but needs to be transformed into an object understood by a full-node. - -## Query Preparation - -The interactions from the users' perspective are a bit different, but the underlying functions are almost identical because they are implementations of the same command defined by the module developer. This step of processing happens within the CLI or REST server and heavily involves a `Context`. - -### Context - -The first thing that is created in the execution of a CLI command is a `Context`, while the REST Server directly provides a `Context` for the REST Request handler. A [Context](../core/context.md) is an immutable object that stores all the data needed to process a request on the user side. In particular, a `Context` stores the following: - -* **Codec**: The [encoder/decoder](../core/encoding.md) used by the application, used to marshal the parameters and query before making the Tendermint RPC request and unmarshal the returned response into a JSON object. -* **Account Decoder**: The account decoder from the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/master/x/auth/spec) module, which translates `[]byte`s into accounts. -* **RPC Client**: The Tendermint RPC Client, or node, to which the request will be relayed to. -* **Keybase**: A [Key Manager](../basics/accounts.md#keybase) used to sign transactions and handle other operations with keys. -* **Output Writer**: A [Writer](https://golang.org/pkg/io/#Writer) used to output the response. -* **Configurations**: The flags configured by the user for this command, including `--height`, specifying the height of the blockchain to query and `--indent`, which indicates to add an indent to the JSON response. - -The `Context` also contains various functions such as `Query()` which retrieves the RPC Client and makes an ABCI call to relay a query to a full-node. - -+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/client/context/context.go#L23-L47 - -The `Context`'s primary role is to store data used during interactions with the end-user and provide methods to interact with this data - it is used before and after the query is processed by the full-node. Specifically, in handling `Query`, the `Context` is utilized to encode the query parameters, retrieve the full-node, and write the output. Prior to being relayed to a full-node, the query needs to be encoded into a `[]byte` form, as full-nodes are application-agnostic and do not understand specific types. The full-node (RPC Client) itself is retrieved using the `Context`, which knows which node the user CLI is connected to. The query is relayed to this full-node to be processed. Finally, the `Context` contains a `Writer` to write output when the response is returned. These steps are further described in later sections. - -### Arguments and Route Creation - -At this point in the lifecycle, the user has created a CLI command or HTTP Request with all of the data they wish to include in their `Query`. A `Context` exists to assist in the rest of the `Query`'s journey. Now, the next step is to parse the command or request, extract the arguments, create a `queryRoute`, and encode everything. These steps all happen on the user side within the interface they are interacting with. - -#### Encoding - -In this case, `Query` contains an [address](../basics/accounts.md#addresses) `delegatorAddress` as its only argument. However, the request can only contain `[]byte`s, as it will be relayed to a consensus engine (e.g. Tendermint Core) of a full-node that has no inherent knowledge of the application types. Thus, the `codec` of `Context` is used to marshal the address. - -Here is what the code looks like for the CLI command: - -```go -delAddr, err := sdk.AccAddressFromBech32(args[0]) -bz, err := cdc.MarshalJSON(types.NewQueryDelegatorParams(delAddr)) -``` - -Here is what the code looks like for the HTTP Request: - -```go -vars := mux.Vars(r) -bech32delegator := vars["delegatorAddr"] -delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) -cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) -if !ok { - return -} -params := types.NewQueryDelegatorParams(delegatorAddr) -``` - -#### Query Route Creation - -Important to note is that there will never be a "query" object created for `Query`; the SDK actually takes a simpler approach. Instead of an object, all the full-node needs to process a query is its `route` which specifies exactly which module to route the query to and the name of this query type. The `route` will be passed to the application `baseapp`, then module, then [querier](../building-modules/query-services.md#legacy-queriers), and each will understand the `route` and pass it to the appropriate next step. [`baseapp`](../core/baseapp.md#query-routing) will understand this query to be a `custom` query in the module `staking`, and the `staking` module querier supports the type `QueryDelegatorDelegations`. Thus, the route will be `"custom/staking/delegatorDelegations"`. - -Here is what the code looks like: - -```go -route := fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryDelegatorDelegations) -``` - -Now, `Query` exists as a set of encoded arguments and a route to a specific module and its query type. It is ready to be relayed to a full-node. - -#### ABCI Query Call - -The `Context` has a `Query()` function used to retrieve the pre-configured node and relay a query to it; the function takes the query `route` and arguments as parameters. It first retrieves the RPC Client (called the [**node**](../core/node.md)) configured by the user to relay this query to, and creates the `ABCIQueryOptions` (parameters formatted for the ABCI call). The node is then used to make the ABCI call, `ABCIQueryWithOptions()`. - -Here is what the code looks like: - -+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/client/context/query.go#L75-L112 - -## RPC - -With a call to `ABCIQueryWithOptions()`, `Query` is received by a [full-node](../core/encoding.md) which will then process the request. Note that, while the RPC is made to the consensus engine (e.g. Tendermint Core) of a full-node, queries are not part of consensus and will not be broadcasted to the rest of the network, as they do not require anything the network needs to agree upon. - -Read more about ABCI Clients and Tendermint RPC in the Tendermint documentation [here](https://tendermint.com/rpc). - -## Application Query Handling - -When a query is received by the full-node after it has been relayed from the underlying consensus engine, it is now being handled within an environment that understands application-specific types and has a copy of the state. [`baseapp`](../core/baseapp.md) implements the ABCI [`Query()`](../core/baseapp.md#query) function and handles four different types of queries: `app`, `store`, `p2p`, and `custom`. The `queryRoute` is parsed such that the first string must be one of the four options, then the rest of the path is parsed within the subroutines handling each type of query. The first three types (`app`, `store`, `p2p`) are purely application-level and thus directly handled by `baseapp` or the stores, but the `custom` query type requires `baseapp` to route the query to a module's [query service](../building-modules/query-services.md). - -Since `Query` is a custom query type from the `staking` module, `baseapp` first parses the path, then uses the `QueryRouter` to retrieve the corresponding querier, and routes the query to the module. The querier is responsible for recognizing this query, retrieving the appropriate values from the application's stores, and returning a response. Read more about query services [here](../building-modules/query-services.md). - -Once a result is received from the querier, `baseapp` begins the process of returning a response to the user. - -## Response - -Since `Query()` is an ABCI function, `baseapp` returns the response as an [`abci.ResponseQuery`](https://tendermint.com/docs/spec/abci/abci.html#messages) type. The `Context` `Query()` routine receives the response and. - -+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/client/context/query.go#L127-L165 - -### CLI Response - -The application [`codec`](../core/encoding.md) is used to unmarshal the response to a JSON and the `Context` prints the output to the command line, applying any configurations such as `--indent`. - -+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/x/staking/client/cli/query.go#L252-L293 - -### REST Response - -The [REST server](./rest.md#rest-server) uses the `Context` to format the response properly, then uses the HTTP package to write the appropriate response or error. - -+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/x/staking/client/rest/utils.go#L115-L148 - -## Next {hide} - -Read about how to build a [Command-Line Interface](./cli.md), or a [REST Interface](./rest.md) {hide} diff --git a/docs/interfaces/rest.md b/docs/interfaces/rest.md deleted file mode 100644 index 00e94b1d9a9d..000000000000 --- a/docs/interfaces/rest.md +++ /dev/null @@ -1,70 +0,0 @@ - - -# REST Interface - -This document describes how to create a REST interface for an SDK **application**. A separate document for creating a [**module**](../building-modules/intro.md) REST interface can be found [here](#../module-interfaces.md#legacy-rest). {synopsis} - -## Pre-requisite Readings - -- [Query Lifecycle](./query-lifecycle.md) {prereq} -- [Application CLI](./cli.md) {prereq} - -## Application REST Interface - -Building the REST Interface for an application is done by [aggregating REST Routes](#registering-routes) defined in the application's modules. This interface is served by a REST Server [REST server](#rest-server), which route requests and output responses in the application itself. The SDK comes with its own REST Server by default. To enable it, the `rest.ServeCommand` command needs to be added as a subcommand of the `rootCmd` in the `main()` function of the [CLI interface](./cli.md): - -```go -rootCmd.AddCommand(rest.ServeCommand(cdc, registerRoutes)) -``` - -Users will then be able to use the application CLI to start a new REST server, a local server through which they can securely interact with the application without downloading the entire state. The command entered by users would look something like this: - -```bash -appcli rest-server --chain-id -``` - -## REST Server - -A REST Server is used to receive and route HTTP Requests, obtain the results from the application, and return a response to the user. The REST Server defined by the SDK `rest` package contains the following: - -- **Router:** A router for HTTP requests. A new router can be instantiated for an application and used to match routes based on path, request method, headers, etc. The SDK uses the [Gorilla Mux Router](https://github.com/gorilla/mux). -- **Context:** A [`Context`](./query-lifecycle.md#context) created for a user interaction. -- **Keybase:** A [Keybase](../basics/accounts.md#keybase) is a key manager. -- **Logger:** A logger from Tendermint `Log`, a log package structured around key-value pairs that allows logging level to be set differently for different keys. The logger takes `Debug()`, `Info()`, and `Error()`s. -- **Listener:** A [listener](https://golang.org/pkg/net/#Listener) from the net package. - -Of the five, the only attribute that application developers need interact with is the `router`: they need to add routes to it so that the REST server can properly handle queries. See the next section for more information on registering routes. - -In order to enable the REST Server in an SDK application, the `rest.ServeCommand` needs to be added to the application's command-line interface. See the [above section](#application-rest-interface) for more information. - -## Registering Routes - -To include routes for each module in an application, the CLI must have some kind of function to register routes in its REST Server. This function is called `RegisterRoutes()`, and is utilized by the `ServeCommand` and must include routes for each of the application's modules. Since each module used by an SDK application implements a [`RegisterRESTRoutes`](../building-modules/module-interfaces.md#legacy-rest) function, application developers simply use the [Module Manager](../building-modules/module-manager.md) to call this function for each module (this is done in the [application's constructor](../basics/app-anatomy.md#constructor-function)). - -At the bare minimum, a `RegisterRoutes()` function should use the SDK client package `RegisterRoutes()` function to be able to route RPC calls, and instruct the application Module Manager to call `RegisterRESTRoutes()` for all of its modules. This is done in the `main.go` file of the CLI (typically located in `./cmd/appcli/main.go`). - -```go -func registerRoutes(rs *rest.RestServer) { - rpc.RegisterRoutes(rs.ClientCtx, rs.Mux) - app.ModuleBasics.RegisterRESTRoutes(rs.ClientCtx, rs.Mux) -} -``` - -This function is specific to the application and passed in to the `ServeCommand`, which should be added to the `rootCmd` as such: - -```go -rootCmd.AddCommand(rest.ServeCommand(cdc, registerRoutes)) -``` - -## Cross-Origin Resource Sharing (CORS) - -[CORS policies](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) are not enabled by default to help with security. If you would like to use the rest-server in a public environment we recommend you provide a reverse proxy, this can be done with [nginx](https://www.nginx.com/). For testing and development purposes there is an `unsafe_cors` flag that can be passed to the cmd to enable accepting cors from everyone. - -```sh -gaiacli rest-server --chain-id=test \ - --laddr=tcp://localhost:1317 \ - --node tcp://localhost:26657 \ - --unsafe-cors -``` diff --git a/docs/run-node/interact-node.md b/docs/run-node/interact-node.md index c7b30c57b073..a07981341fe7 100644 --- a/docs/run-node/interact-node.md +++ b/docs/run-node/interact-node.md @@ -62,7 +62,7 @@ Since the code generation library largely depends on your own tech stack, we wil [grpcurl])https://github.com/fullstorydev/grpcurl is like `curl` but for gRPC. It is also available as a Go library, but we will use it only as a CLI command for debugging and testing purposes. Follow the instructions in the previous link to install it. -Assuming you have a local node running (either a localnet, or connected a live network), you should be able to run the following command to list the Protobuf services available (you can replace `localhost:9000` by the gRPC server endpoint of another node, which is configured under the `grpc.address` field inside `app.toml`): +Assuming you have a local node running (either a localnet, or connected a live network), you should be able to run the following command to list the Protobuf services available (you can replace `localhost:9000` by the gRPC server endpoint of another node, which is configured under the `grpc.address` field inside [`app.toml`](../run-node/run-node.md#configuring-the-node-using-apptoml)): ```bash grpcurl -plaintext localhost:9090 list @@ -217,7 +217,7 @@ curl \ Make sure to replace `localhost:1317` with the REST endpoint of your node, configured under the `api.address` field. -The list of all available REST endpoints is available as a Swagger specification file, it can be viewed at `localhost:1317/swagger`. Make sure that the `api.swagger` field is set to true in your `app.toml` file. +The list of all available REST endpoints is available as a Swagger specification file, it can be viewed at `localhost:1317/swagger`. Make sure that the `api.swagger` field is set to true in your [`app.toml`](../run-node/run-node.md#configuring-the-node-using-apptoml) file. ### Query for historical state using REST @@ -233,6 +233,10 @@ curl \ Assuming the state at that block has not yet been pruned by the node, this query should return a non-empty response. +### Cross-Origin Resource Sharing (CORS) + +[CORS policies](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) are not enabled by default to help with security. If you would like to use the rest-server in a public environment we recommend you provide a reverse proxy, this can be done with [nginx](https://www.nginx.com/). For testing and development purposes there is an `enabled-unsafe-cors` field inside [`app.toml`](../run-node/run-node.md#configuring-the-node-using-apptoml). + ## Next {hide} Sending transactions using gRPC and REST requires some additional steps: generating the transaction, signing it, and finally broadcasting it. Read about [generating and signing transactions](./txs.md). {hide} diff --git a/docs/run-node/run-node.md b/docs/run-node/run-node.md index 393172b9aa0c..aee7d84e1301 100644 --- a/docs/run-node/run-node.md +++ b/docs/run-node/run-node.md @@ -85,6 +85,12 @@ The previous command allow you to run a single node. This is enough for the next The naive way would be to run the same commands again in separate terminal windows. This is possible, however in the SDK, we leverage the power of [Docker Compose](https://docs.docker.com/compose/) to run a localnet. If you need inspiration on how to set up your own localnet with Docker Compose, you can have a look at the SDK's [`docker-compose.yml`](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/docker-compose.yml). +## Configuring the Node Using `app.toml` + +The Cosmos SDK automatically generates an `app.toml` file inside `~/.simapp/config`. This file is used to configure your app, such as state pruning strategies, telemetry, gRPC and REST servers configuration, state sync... The file itself is heavily commented, please refer to it directly to tweak your node. + +Make sure to restart your node after modifying `app.toml`. + ## Next {hide} Read about the [Interacting with your Node](./interact-node.md) {hide} From 411b04d3aa924369d4faebe5a52ca4187f365c9b Mon Sep 17 00:00:00 2001 From: Segue Date: Mon, 18 Jan 2021 19:45:06 +0800 Subject: [PATCH 043/152] Fix ibc client (#8341) * fix-ibc-client * add changelog --- CHANGELOG.md | 1 + x/ibc/core/04-channel/client/utils/utils.go | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa8f7658ec25..bec47aa9bdf0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes * (x/auth) [\#8287](https://github.com/cosmos/cosmos-sdk/pull/8287) Fix `tx sign --signature-only` to return correct sequence value in signature. + * (x/ibc) [\#8341](https://github.com/cosmos/cosmos-sdk/pull/8341) Fix query latest consensus state. ## [v0.40.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0) - 2021-01-08 diff --git a/x/ibc/core/04-channel/client/utils/utils.go b/x/ibc/core/04-channel/client/utils/utils.go index c10dc05c7fd3..167e05d048e9 100644 --- a/x/ibc/core/04-channel/client/utils/utils.go +++ b/x/ibc/core/04-channel/client/utils/utils.go @@ -133,8 +133,9 @@ func QueryLatestConsensusState( if err != nil { return nil, clienttypes.Height{}, clienttypes.Height{}, err } - clientState, err := clienttypes.UnpackClientState(clientRes.IdentifiedClientState.ClientState) - if err != nil { + + var clientState exported.ClientState + if err := clientCtx.InterfaceRegistry.UnpackAny(clientRes.IdentifiedClientState.ClientState, &clientState); err != nil { return nil, clienttypes.Height{}, clienttypes.Height{}, err } @@ -148,8 +149,8 @@ func QueryLatestConsensusState( return nil, clienttypes.Height{}, clienttypes.Height{}, err } - consensusState, err := clienttypes.UnpackConsensusState(res.ConsensusState) - if err != nil { + var consensusState exported.ConsensusState + if err := clientCtx.InterfaceRegistry.UnpackAny(res.ConsensusState, &consensusState); err != nil { return nil, clienttypes.Height{}, clienttypes.Height{}, err } From e957fad1a7ffd73712cd681116c9b6e09fa3e60b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Jan 2021 12:47:24 +0000 Subject: [PATCH 044/152] build(deps): bump vuepress-theme-cosmos from 1.0.179 to 1.0.180 in /docs (#8356) Bumps [vuepress-theme-cosmos](https://github.com/cosmos/vuepress-theme-cosmos) from 1.0.179 to 1.0.180. - [Release notes](https://github.com/cosmos/vuepress-theme-cosmos/releases) - [Commits](https://github.com/cosmos/vuepress-theme-cosmos/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- docs/package-lock.json | 1336 ++++++++++++++++------------------------ docs/package.json | 2 +- 2 files changed, 530 insertions(+), 808 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 0c83b5840d4b..d6bc2513349f 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -120,9 +120,9 @@ } }, "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", "requires": { "@babel/highlight": "^7.10.4" } @@ -188,11 +188,11 @@ } }, "@babel/generator": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.10.tgz", - "integrity": "sha512-6mCdfhWgmqLdtTkhXjnIz0LcdVCd26wS2JXRtj2XY0u5klDsXBREA/pG5NVOuVnF2LUrBGNFtQkIqqTbblg0ww==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz", + "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==", "requires": { - "@babel/types": "^7.12.10", + "@babel/types": "^7.12.11", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, @@ -279,13 +279,13 @@ } }, "@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz", + "integrity": "sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA==", "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" + "@babel/helper-get-function-arity": "^7.12.10", + "@babel/template": "^7.12.7", + "@babel/types": "^7.12.11" } }, "@babel/helper-get-function-arity": { @@ -360,14 +360,14 @@ } }, "@babel/helper-replace-supers": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz", - "integrity": "sha512-5YILoed0ZyIpF4gKcpZitEnXEJ9UoDRki1Ey6xz46rxOzfNMAhVIJMoune1hmPVxh40LRv1+oafz7UsWX+vyWA==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz", + "integrity": "sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA==", "requires": { - "@babel/helper-member-expression-to-functions": "^7.12.1", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/traverse": "^7.12.5", - "@babel/types": "^7.12.5" + "@babel/helper-member-expression-to-functions": "^7.12.7", + "@babel/helper-optimise-call-expression": "^7.12.10", + "@babel/traverse": "^7.12.10", + "@babel/types": "^7.12.11" } }, "@babel/helper-simple-access": { @@ -387,22 +387,22 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", - "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz", + "integrity": "sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g==", "requires": { - "@babel/types": "^7.11.0" + "@babel/types": "^7.12.11" } }, "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==" + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==" }, "@babel/helper-validator-option": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz", - "integrity": "sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A==" + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz", + "integrity": "sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw==" }, "@babel/helper-wrap-function": { "version": "7.12.3", @@ -436,14 +436,14 @@ } }, "@babel/parser": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.10.tgz", - "integrity": "sha512-PJdRPwyoOqFAWfLytxrWwGrAxghCgh/yTNCYciOz8QgjflA7aZhECPZAa2VUedKg2+QMWkI0L9lynh2SNmNEgA==" + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz", + "integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==" }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz", - "integrity": "sha512-d+/o30tJxFxrA1lhzJqiUcEJdI6jKlNregCv5bASeGf2Q4MXmnwH7viDo7nhx1/ohf09oaH8j1GVYG/e3Yqk6A==", + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz", + "integrity": "sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A==", "requires": { "@babel/helper-plugin-utils": "^7.10.4", "@babel/helper-remap-async-to-generator": "^7.12.1", @@ -460,9 +460,9 @@ } }, "@babel/plugin-proposal-decorators": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.12.1.tgz", - "integrity": "sha512-knNIuusychgYN8fGJHONL0RbFxLGawhXOJNLBk75TniTsZZeA+wdkDuv6wp4lGwzQEKjZi6/WYtnb3udNPmQmQ==", + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.12.12.tgz", + "integrity": "sha512-fhkE9lJYpw2mjHelBpM2zCbaA11aov2GJs7q4cFaXNrWx0H3bW58H9Esy2rdtYOghFBEYUDRIpvlgi+ZD+AvvQ==", "requires": { "@babel/helper-create-class-features-plugin": "^7.12.1", "@babel/helper-plugin-utils": "^7.10.4", @@ -709,9 +709,9 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.1.tgz", - "integrity": "sha512-zJyAC9sZdE60r1nVQHblcfCj29Dh2Y0DOvlMkcqSo0ckqjiCwNiUezUKw+RjOCwGfpLRwnAeQ2XlLpsnGkvv9w==", + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz", + "integrity": "sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ==", "requires": { "@babel/helper-plugin-utils": "^7.10.4" } @@ -981,15 +981,15 @@ } }, "@babel/preset-env": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.10.tgz", - "integrity": "sha512-Gz9hnBT/tGeTE2DBNDkD7BiWRELZt+8lSysHuDwmYXUIvtwZl0zI+D6mZgXZX0u8YBlLS4tmai9ONNY9tjRgRA==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.11.tgz", + "integrity": "sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw==", "requires": { "@babel/compat-data": "^7.12.7", "@babel/helper-compilation-targets": "^7.12.5", "@babel/helper-module-imports": "^7.12.5", "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-validator-option": "^7.12.1", + "@babel/helper-validator-option": "^7.12.11", "@babel/plugin-proposal-async-generator-functions": "^7.12.1", "@babel/plugin-proposal-class-properties": "^7.12.1", "@babel/plugin-proposal-dynamic-import": "^7.12.1", @@ -1018,7 +1018,7 @@ "@babel/plugin-transform-arrow-functions": "^7.12.1", "@babel/plugin-transform-async-to-generator": "^7.12.1", "@babel/plugin-transform-block-scoped-functions": "^7.12.1", - "@babel/plugin-transform-block-scoping": "^7.12.1", + "@babel/plugin-transform-block-scoping": "^7.12.11", "@babel/plugin-transform-classes": "^7.12.1", "@babel/plugin-transform-computed-properties": "^7.12.1", "@babel/plugin-transform-destructuring": "^7.12.1", @@ -1048,7 +1048,7 @@ "@babel/plugin-transform-unicode-escapes": "^7.12.1", "@babel/plugin-transform-unicode-regex": "^7.12.1", "@babel/preset-modules": "^0.1.3", - "@babel/types": "^7.12.10", + "@babel/types": "^7.12.11", "core-js-compat": "^3.8.0", "semver": "^5.5.0" }, @@ -1098,16 +1098,16 @@ } }, "@babel/traverse": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.10.tgz", - "integrity": "sha512-6aEtf0IeRgbYWzta29lePeYSk+YAFIC3kyqESeft8o5CkFlYIMX+EQDDWEiAQ9LHOA3d0oHdgrSsID/CKqXJlg==", - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.10", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.12.10", - "@babel/types": "^7.12.10", + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz", + "integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==", + "requires": { + "@babel/code-frame": "^7.12.11", + "@babel/generator": "^7.12.11", + "@babel/helper-function-name": "^7.12.11", + "@babel/helper-split-export-declaration": "^7.12.11", + "@babel/parser": "^7.12.11", + "@babel/types": "^7.12.12", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.19" @@ -1129,11 +1129,11 @@ } }, "@babel/types": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.10.tgz", - "integrity": "sha512-sf6wboJV5mGyip2hIpDSKsr80RszPinEFjsHTalMxZAZkoQ2/2yQzxlcFN52SJqsyPfLtPmenL4g2KB3KJXPDw==", + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", "requires": { - "@babel/helper-validator-identifier": "^7.10.4", + "@babel/helper-validator-identifier": "^7.12.11", "lodash": "^4.17.19", "to-fast-properties": "^2.0.0" }, @@ -1251,9 +1251,9 @@ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" }, "@types/node": { - "version": "14.14.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.12.tgz", - "integrity": "sha512-ASH8OPHMNlkdjrEdmoILmzFfsJICvhBsFfAum4aKZ/9U4B6M6tTmTPh+f3ttWdD74CEGV5XvXWkbyfSdXaTd7g==" + "version": "14.14.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.21.tgz", + "integrity": "sha512-cHYfKsnwllYhjOzuC5q1VpguABBeecUp24yFluHpn/BQaVxB1CuQ1FSRZCzrPxrkIfWISXV2LbeoBthLWg0+0A==" }, "@types/q": { "version": "1.5.4", @@ -1266,21 +1266,21 @@ "integrity": "sha512-QOi5OW45e2R20VygMSNhyQHvpdUwQZqGPc748JLGCYEy+yp8fNFNdbNIGAgZmi9e+2JHPd6i6idRuqivyicIkA==" }, "@vue/babel-helper-vue-transform-on": { - "version": "1.0.0-rc.2", - "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.0.0-rc.2.tgz", - "integrity": "sha512-1+7CwjQ0Kasml6rHoNQUmbISwqLNNfFVBUcZl6QBremUl296ZmLrVQPqJP5pyAAWjZke5bpI1hlj+LVVuT7Jcg==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.0.2.tgz", + "integrity": "sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA==" }, "@vue/babel-plugin-jsx": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.0.0-rc.4.tgz", - "integrity": "sha512-ifzYc0jfLqiQebfqzKrJGfmQFE1lIgFlE9Ive8hQMJS/GC9Y+mNtHpqmWyqljbFGsqmsxmMRNFdAUgz0HZN1rg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.0.2.tgz", + "integrity": "sha512-1uZlQCLCeuqJgDYLCmg3qfsvTVtOQiXh278ES4bvPTYYbv2Bi/rElLETK6AdjI9xxzyTUf5n1QEiH8Xxz0eZrg==", "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/plugin-syntax-jsx": "^7.0.0", "@babel/template": "^7.0.0", "@babel/traverse": "^7.0.0", "@babel/types": "^7.0.0", - "@vue/babel-helper-vue-transform-on": "^1.0.0-rc.2", + "@vue/babel-helper-vue-transform-on": "^1.0.2", "camelcase": "^6.0.0", "html-tags": "^3.1.0", "svg-tags": "^1.0.0" @@ -1314,9 +1314,9 @@ } }, "@vue/babel-preset-app": { - "version": "4.5.9", - "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-4.5.9.tgz", - "integrity": "sha512-d2H4hFnJsGnZtJAAZIbo1dmQJ2SI1MYix1Tc9/etlnJtCDPRHeCNodCSeuLgDwnoAyT3unzyHmTtaO56KRDuOQ==", + "version": "4.5.10", + "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-4.5.10.tgz", + "integrity": "sha512-IHOyfWqgNNM863NjGmX6s2MIF+ILkJZardHcr7bGrxu5mNBT+p0GOGRQU4sN/adDkEQ9cyAxokm/GIeeoRrnOg==", "requires": { "@babel/core": "^7.11.0", "@babel/helper-compilation-targets": "^7.9.6", @@ -1337,9 +1337,9 @@ }, "dependencies": { "core-js": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.1.tgz", - "integrity": "sha512-9Id2xHY1W7m8hCl8NkhQn5CufmF/WuR30BTRewvCXc1aZd3kMECwNZ69ndLbekKfakw9Rf2Xyc+QR6E7Gg+obg==" + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.2.tgz", + "integrity": "sha512-FfApuSRgrR6G5s58casCBd9M2k+4ikuu4wbW6pJyYU7bd9zvFc9qf7vr5xmrZOhT9nn+8uwlH1oRR9jTnFoA3A==" } } }, @@ -1465,17 +1465,17 @@ } }, "@vuepress/core": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@vuepress/core/-/core-1.7.1.tgz", - "integrity": "sha512-M5sxZq30Ke1vXa4ZZjk6185fwtpiJOqzXNnzcIe0GxtvtaF8Yij6b+KqQKlUJnnUXm+CKxiLCr8PTzDY26N7yw==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@vuepress/core/-/core-1.8.0.tgz", + "integrity": "sha512-DrHx3gXa5rUDdvjcUHhmZg1DccMwc3kiYpgtbKCuJpHksz9eAVuOxbcy/b6TGRbbY4Q5EA2Fs3kI9hvPjYdCrQ==", "requires": { "@babel/core": "^7.8.4", "@vue/babel-preset-app": "^4.1.2", - "@vuepress/markdown": "1.7.1", - "@vuepress/markdown-loader": "1.7.1", - "@vuepress/plugin-last-updated": "1.7.1", - "@vuepress/plugin-register-components": "1.7.1", - "@vuepress/shared-utils": "1.7.1", + "@vuepress/markdown": "1.8.0", + "@vuepress/markdown-loader": "1.8.0", + "@vuepress/plugin-last-updated": "1.8.0", + "@vuepress/plugin-register-components": "1.8.0", + "@vuepress/shared-utils": "1.8.0", "autoprefixer": "^9.5.1", "babel-loader": "^8.0.4", "cache-loader": "^3.0.0", @@ -1510,18 +1510,18 @@ }, "dependencies": { "core-js": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.1.tgz", - "integrity": "sha512-9Id2xHY1W7m8hCl8NkhQn5CufmF/WuR30BTRewvCXc1aZd3kMECwNZ69ndLbekKfakw9Rf2Xyc+QR6E7Gg+obg==" + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.2.tgz", + "integrity": "sha512-FfApuSRgrR6G5s58casCBd9M2k+4ikuu4wbW6pJyYU7bd9zvFc9qf7vr5xmrZOhT9nn+8uwlH1oRR9jTnFoA3A==" } } }, "@vuepress/markdown": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@vuepress/markdown/-/markdown-1.7.1.tgz", - "integrity": "sha512-Ava9vJECHG1+RC53ut1dXSze35IH5tc3qesC06Ny37WS93iDSQy09j8y+a0Lugy12j1369+QQeRFWa40tdHczA==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@vuepress/markdown/-/markdown-1.8.0.tgz", + "integrity": "sha512-f2yhoIHTD6gaPeLLidkxuytKGQCT6Gopm0fpyKZwfFZaWWz5+RPPGevq5UTmTb+5vvO2Li44HJc1EV7QONOw9Q==", "requires": { - "@vuepress/shared-utils": "1.7.1", + "@vuepress/shared-utils": "1.8.0", "markdown-it": "^8.4.1", "markdown-it-anchor": "^5.0.2", "markdown-it-chain": "^1.3.0", @@ -1550,19 +1550,19 @@ } }, "@vuepress/markdown-loader": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@vuepress/markdown-loader/-/markdown-loader-1.7.1.tgz", - "integrity": "sha512-GM1F/tRhP9qZydTC89FXJPlLH+BmZijMKom5BYLAMEXsU20A9kABTRoatPjOUbZuKT+gn03JgG97qVd8xa/ETw==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@vuepress/markdown-loader/-/markdown-loader-1.8.0.tgz", + "integrity": "sha512-ykYTNe4mC/0CxyEfyM9+oYJqFvOMZWw5qiNZVfg2t+Ip8nVR2pFhQ6fJe07Pbtc59eT4awKSEd8/kcjhTpfeZA==", "requires": { - "@vuepress/markdown": "1.7.1", + "@vuepress/markdown": "1.8.0", "loader-utils": "^1.1.0", "lru-cache": "^5.1.1" } }, "@vuepress/plugin-active-header-links": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@vuepress/plugin-active-header-links/-/plugin-active-header-links-1.7.1.tgz", - "integrity": "sha512-Wgf/oB9oPZLnYoLjQ/xbQc4Qa3RU5tXAo2dB4Xl/7bUL6SqBxO866kX3wPxKdSOIL58tq8iH9XbUe3Sxi8/ISQ==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-active-header-links/-/plugin-active-header-links-1.8.0.tgz", + "integrity": "sha512-0SqdkJLJSQqhPTgGccu/ev5zRCfeKKMkyPnUMJYsQe4zGhSosmwLcfB7LDo/VLqLhRipipzBnONESr12OgI4SQ==", "requires": { "lodash.debounce": "^4.0.8" } @@ -1573,38 +1573,38 @@ "integrity": "sha512-27fQzRMsqGYpMf+ruyhsdfLv/n6z6b6LutFLE/pH66Itlh6ox9ew31x0pqYBbWIC/a4lBfXYUwFvi+DEvlb1EQ==" }, "@vuepress/plugin-last-updated": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@vuepress/plugin-last-updated/-/plugin-last-updated-1.7.1.tgz", - "integrity": "sha512-VW5jhBuO0WRHDsBmFsKC6QtEyBLCgyhuH9nQ65aairCn3tdoJPz0uQ4g3lr/boVbgsPexO677Sn3dRPgYqnMug==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-last-updated/-/plugin-last-updated-1.8.0.tgz", + "integrity": "sha512-fBwtlffAabpTTalUMPSaJy/5fp3WpIA1FdWOfFcQ12X6179tupZB8fnueNsVJGBvGcdw8fbyzh5C9yKAq9lR/w==", "requires": { "cross-spawn": "^6.0.5" } }, "@vuepress/plugin-nprogress": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@vuepress/plugin-nprogress/-/plugin-nprogress-1.7.1.tgz", - "integrity": "sha512-KtqfI3RitbsEbm22EhbooTvhjfMf6zttKlbND7LcyJwP3MEPVYyzQJuET03hk9z4SgCfNV2r/W3sYyejzzTMog==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-nprogress/-/plugin-nprogress-1.8.0.tgz", + "integrity": "sha512-JmjeJKKWhbF/8z+EnY8BCWHoHKhUWfqXjXOfV+xifITl6BJlf53I/jLFpX7Sij8Whe+SKjH7kNvc+hioUdwJQw==", "requires": { "nprogress": "^0.2.0" } }, "@vuepress/plugin-register-components": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@vuepress/plugin-register-components/-/plugin-register-components-1.7.1.tgz", - "integrity": "sha512-MlFdH6l3rTCJlGMvyssXVG998cq5LSMzxCuQLYcRdtHQT4HbikIcV4HSPGarWInD1mP12+qX/PvKUawGwp1eVg==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-register-components/-/plugin-register-components-1.8.0.tgz", + "integrity": "sha512-ztafaAxn7XFS4F8z51d+QQB6DNAUG54wBSdfKydfnHbAYgtxoALzPlJW7FKQdxvZKxqGrJa9e4rkoZsat13KRQ==", "requires": { - "@vuepress/shared-utils": "1.7.1" + "@vuepress/shared-utils": "1.8.0" } }, "@vuepress/plugin-search": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@vuepress/plugin-search/-/plugin-search-1.7.1.tgz", - "integrity": "sha512-OmiGM5eYg9c+uC50b6/cSxAhqxfD7AIui6JEztFGeECrlP33RLHmteXK9YBBZjp5wTNmoYs+NXI/cWggYUPW8Q==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-search/-/plugin-search-1.8.0.tgz", + "integrity": "sha512-LlOCPg7JJ3I9WEpiBU8vCEFp6I5sa3OBu6SFHk+uK9iyKHwJYdRs4VK9x+igG40Rt/OIDRDo3c9SbLX/E/kqeA==" }, "@vuepress/shared-utils": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@vuepress/shared-utils/-/shared-utils-1.7.1.tgz", - "integrity": "sha512-ydB2ZKsFZE6hFRb9FWqzZksxAPIMJjtBawk50RP6F+YX5HbID/HlyYYZM9aDSbk6RTkjgB5UzJjggA2xM8POlw==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@vuepress/shared-utils/-/shared-utils-1.8.0.tgz", + "integrity": "sha512-CVNMiYBntQyb4CuyS4KzmglDqsuBpj8V4QMzL9gCSoMv0VmwKx05fZedu+r0G5OcxYN4qjnu99yl9G6zWhOU9w==", "requires": { "chalk": "^2.3.2", "escape-html": "^1.0.3", @@ -1618,13 +1618,13 @@ } }, "@vuepress/theme-default": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@vuepress/theme-default/-/theme-default-1.7.1.tgz", - "integrity": "sha512-a9HeTrlcWQj3ONHiABmlN2z9TyIxKfQtLsA8AL+WgjN3PikhFuZFIJGzfr+NLt67Y9oiI+S9ZfiaVyvWM+7bWQ==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@vuepress/theme-default/-/theme-default-1.8.0.tgz", + "integrity": "sha512-CueCaANfICFbLnEL78YxSjgCHXL7mkgQI/cfyEHBgxlr247cYJQ+9IFDQIS0fJNuzHdLRy9UFUvVrCu6go8PUg==", "requires": { - "@vuepress/plugin-active-header-links": "1.7.1", - "@vuepress/plugin-nprogress": "1.7.1", - "@vuepress/plugin-search": "1.7.1", + "@vuepress/plugin-active-header-links": "1.8.0", + "@vuepress/plugin-nprogress": "1.8.0", + "@vuepress/plugin-search": "1.8.0", "docsearch.js": "^2.5.2", "lodash": "^4.17.15", "stylus": "^0.54.8", @@ -2141,17 +2141,17 @@ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, "axios": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.0.tgz", - "integrity": "sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", "requires": { "follow-redirects": "^1.10.0" }, "dependencies": { "follow-redirects": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", - "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==" + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz", + "integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg==" } } }, @@ -2542,6 +2542,23 @@ "parse-asn1": "^5.1.5", "readable-stream": "^3.6.0", "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } } }, "browserify-zlib": { @@ -2553,15 +2570,15 @@ } }, "browserslist": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.0.tgz", - "integrity": "sha512-/j6k8R0p3nxOC6kx5JGAxsnhc9ixaWJfYc+TNTzxg6+ARaESAvQGV7h0uNOB4t+pLQJZWzcrMxXOxjgsCj3dqQ==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.1.tgz", + "integrity": "sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==", "requires": { - "caniuse-lite": "^1.0.30001165", + "caniuse-lite": "^1.0.30001173", "colorette": "^1.2.1", - "electron-to-chromium": "^1.3.621", + "electron-to-chromium": "^1.3.634", "escalade": "^3.1.1", - "node-releases": "^1.1.67" + "node-releases": "^1.1.69" } }, "buffer": { @@ -2605,9 +2622,9 @@ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, "cac": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.6.1.tgz", - "integrity": "sha512-uhki4T3Ax68hw7Dufi0bATVAF8ayBSwOKUEJHjObPrUN4tlQ8Lf7oljpTje/mArLxYN0D743c2zJt4C1bVTCqg==" + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.1.tgz", + "integrity": "sha512-LfGt47+ugCY65W4yUEyxnZKd/tJSBJD/gUAxQGiQjH7yqdhbaX2XN0Rli4+0W0DJiDONmYeh0TlJxMtXGZspIg==" }, "cacache": { "version": "12.0.4", @@ -2787,12 +2804,12 @@ } }, "call-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", - "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "requires": { "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.0" + "get-intrinsic": "^1.0.2" } }, "call-me-maybe": { @@ -2847,9 +2864,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001165", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001165.tgz", - "integrity": "sha512-8cEsSMwXfx7lWSUMA2s08z9dIgsnR5NAqjXP23stdsU3AUWkCr/rr4s4OFtHXn5XXr6+7kam3QFVoYyXNPdJPA==" + "version": "1.0.30001178", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001178.tgz", + "integrity": "sha512-VtdZLC0vsXykKni8Uztx45xynytOi71Ufx9T8kHptSw9AL4dpqailUJJHavttuzUe1KYuBYtChiWv+BAb7mPmQ==" }, "caseless": { "version": "0.12.0", @@ -2884,23 +2901,29 @@ } }, "cheerio": { - "version": "1.0.0-rc.3", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", - "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", + "version": "1.0.0-rc.5", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.5.tgz", + "integrity": "sha512-yoqps/VCaZgN4pfXtenwHROTp8NG6/Hlt4Jpz2FEP0ZJQ+ZUkVDd0hAPDNKhj3nakpfPt/CNs57yEtxD1bXQiw==", "requires": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.1", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash": "^4.15.0", - "parse5": "^3.0.1" - }, - "dependencies": { - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - } + "cheerio-select-tmp": "^0.1.0", + "dom-serializer": "~1.2.0", + "domhandler": "^4.0.0", + "entities": "~2.1.0", + "htmlparser2": "^6.0.0", + "parse5": "^6.0.0", + "parse5-htmlparser2-tree-adapter": "^6.0.0" + } + }, + "cheerio-select-tmp": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/cheerio-select-tmp/-/cheerio-select-tmp-0.1.1.tgz", + "integrity": "sha512-YYs5JvbpU19VYJyj+F7oYrIE2BOll1/hRU7rEy/5+v9BzkSo3bK81iAeeQEMI92vRIxz677m72UmJUiVwwgjfQ==", + "requires": { + "css-select": "^3.1.2", + "css-what": "^4.0.0", + "domelementtype": "^2.1.0", + "domhandler": "^4.0.0", + "domutils": "^2.4.4" } }, "chokidar": { @@ -3124,11 +3147,6 @@ "requires": { "ms": "2.0.0" } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, @@ -3146,35 +3164,6 @@ "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "configstore": { @@ -3235,13 +3224,6 @@ "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", "requires": { "safe-buffer": "5.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } } }, "content-type": { @@ -3255,13 +3237,6 @@ "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", "requires": { "safe-buffer": "~5.1.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } } }, "cookie": { @@ -3431,11 +3406,11 @@ "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" }, "core-js-compat": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.1.tgz", - "integrity": "sha512-a16TLmy9NVD1rkjUGbwuyWkiDoN0FDpAwrfLONvHFQx0D9k7J9y0srwMT8QP/Z6HE3MIFaVynEeYwZwPX1o5RQ==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.2.tgz", + "integrity": "sha512-LO8uL9lOIyRRrQmZxHZFl1RV+ZbcsAkFWTktn5SmH40WgLtSNYN4m4W2v9ONT147PxBY/XrRhrWq8TlvObyUjQ==", "requires": { - "browserslist": "^4.15.0", + "browserslist": "^4.16.0", "semver": "7.0.0" }, "dependencies": { @@ -3619,14 +3594,15 @@ } }, "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-3.1.2.tgz", + "integrity": "sha512-qmss1EihSuBNWNNhHjxzxSfJoFBM/lERB/Q4EnsJQQC62R2evJDW481091oAdOr9uh46/0n4nrg0It5cAnj1RA==", "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" + "boolbase": "^1.0.0", + "css-what": "^4.0.0", + "domhandler": "^4.0.0", + "domutils": "^2.4.3", + "nth-check": "^2.0.0" } }, "css-select-base-adapter": { @@ -3644,9 +3620,9 @@ } }, "css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-4.0.0.tgz", + "integrity": "sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A==" }, "cssesc": { "version": "3.0.0", @@ -4066,19 +4042,13 @@ } }, "dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.2.0.tgz", + "integrity": "sha512-n6kZFH/KlCrqs/1GHMOd5i2fd/beQHuehKdWvNNffbGHTr/almdhuVvTVFb3V7fglz+nC50fFusu3lY33h12pA==", "requires": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - }, - "dependencies": { - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - } + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "entities": "^2.0.0" } }, "dom-walk": { @@ -4092,25 +4062,26 @@ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" }, "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz", + "integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==" }, "domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.0.0.tgz", + "integrity": "sha512-KPTbnGQ1JeEMQyO1iYXoagsI6so/C96HZiFyByU3T6iAzpXn8EGEvct6unm1ZGoed8ByO2oirxgwxBmqKF9haA==", "requires": { - "domelementtype": "1" + "domelementtype": "^2.1.0" } }, "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.4.4.tgz", + "integrity": "sha512-jBC0vOsECI4OMdD0GC9mGn7NXPLb+Qt6KW1YDQzeQYRUFKmNG8lh7mO5HiELfr+lLQE7loDVI4QcAxV80HS+RA==", "requires": { - "dom-serializer": "0", - "domelementtype": "1" + "dom-serializer": "^1.0.1", + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0" } }, "dot-prop": { @@ -4135,35 +4106,6 @@ "inherits": "^2.0.1", "readable-stream": "^2.0.0", "stream-shift": "^1.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "ecc-jsbn": { @@ -4181,9 +4123,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "version": "1.3.621", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.621.tgz", - "integrity": "sha512-FeIuBzArONbAmKmZIsZIFGu/Gc9AVGlVeVbhCq+G2YIl6QkT0TDn2HKN/FMf1btXEB9kEmIuQf3/lBTVAbmFOg==" + "version": "1.3.641", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.641.tgz", + "integrity": "sha512-b0DLhsHSHESC1I+Nx6n4w4Lr61chMd3m/av1rZQhS2IXTzaS5BMM5N+ldWdMIlni9CITMRM09m8He4+YV/92TA==" }, "elliptic": { "version": "6.5.3", @@ -4230,9 +4172,9 @@ } }, "enhanced-resolve": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", - "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", "requires": { "graceful-fs": "^4.1.2", "memory-fs": "^0.5.0", @@ -4247,33 +4189,6 @@ "errno": "^0.1.3", "readable-stream": "^2.0.1" } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } } } }, @@ -4297,9 +4212,9 @@ "integrity": "sha512-46+j5QxbPWza0PB1i15nZx0xQ4I/EfQxg9J8Had3b408SV63nEtor2e+oiY63amTo9KTuh2a3XLObNwduxYwwA==" }, "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", "requires": { "prr": "~1.0.1" } @@ -4313,22 +4228,24 @@ } }, "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "version": "1.18.0-next.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz", + "integrity": "sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==", "requires": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2", "has": "^1.0.3", "has-symbols": "^1.0.1", "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", + "is-negative-zero": "^2.0.1", "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", + "object-inspect": "^1.9.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.3", + "string.prototype.trimstart": "^1.0.3" } }, "es-to-primitive": { @@ -4537,11 +4454,6 @@ "requires": { "ms": "2.0.0" } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, @@ -4638,9 +4550,9 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", "requires": { "websocket-driver": ">=0.5.1" } @@ -4746,35 +4658,6 @@ "requires": { "inherits": "^2.0.3", "readable-stream": "^2.3.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "follow-redirects": { @@ -4835,35 +4718,6 @@ "requires": { "inherits": "^2.0.1", "readable-stream": "^2.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "fs-extra": { @@ -4885,35 +4739,6 @@ "iferr": "^0.1.5", "imurmurhash": "^0.1.4", "readable-stream": "1 || 2" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "fs.realpath": { @@ -4952,9 +4777,9 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz", - "integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz", + "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==", "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -5029,11 +4854,11 @@ } }, "global-dirs": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", - "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", + "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", "requires": { - "ini": "^1.3.5" + "ini": "1.3.7" } }, "globals": { @@ -5186,6 +5011,23 @@ "inherits": "^2.0.4", "readable-stream": "^3.6.0", "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } } }, "hash-sum": { @@ -5252,35 +5094,6 @@ "obuf": "^1.0.0", "readable-stream": "^2.0.1", "wbuf": "^1.1.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "hsl-regex": { @@ -5299,9 +5112,9 @@ "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==" }, "html-entities": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz", - "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", + "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==" }, "html-minifier": { "version": "3.5.21", @@ -5341,23 +5154,14 @@ "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==" }, "htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "requires": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - }, - "dependencies": { - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - } + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.0.0.tgz", + "integrity": "sha512-numTQtDZMoh78zJpaNdJ9MXb2cv5G3jwUoe3dMQODubZvLoGvTE/Ofp6sHvH8OGKcN/8A47pGLi/k58xHP/Tfw==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.4.4", + "entities": "^2.0.0" } }, "http-cache-semantics": { @@ -5389,6 +5193,11 @@ } } }, + "http-parser-js": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", + "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==" + }, "http-proxy": { "version": "1.18.1", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", @@ -6255,9 +6064,9 @@ } }, "markdown-it": { - "version": "12.0.3", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.3.tgz", - "integrity": "sha512-M57RsMv+QQmJHz1yCu0gTJRMx/LlxRPtrrw+2kb/CpDVK/graCmWO0qfNnz/SE1FCNdyq3pkMMZ+itTnyT/YGA==", + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.4.tgz", + "integrity": "sha512-34RwOXZT8kyuOJy25oJNJoulO8L0bTHYWXcdZBYZqFnjIy3NgjeoM3FmPXIOFQ26/lSHYMr8oc62B6adxXcb3Q==", "requires": { "argparse": "^2.0.1", "entities": "~2.1.0", @@ -6357,35 +6166,6 @@ "requires": { "errno": "^0.1.3", "readable-stream": "^2.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "merge-descriptors": { @@ -6467,21 +6247,21 @@ } }, "mime": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", - "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.0.tgz", + "integrity": "sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==" }, "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==" }, "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "version": "2.1.28", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", + "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", "requires": { - "mime-db": "1.44.0" + "mime-db": "1.45.0" } }, "mimic-response": { @@ -6731,42 +6511,13 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, "node-releases": { - "version": "1.1.67", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.67.tgz", - "integrity": "sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg==" + "version": "1.1.69", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.69.tgz", + "integrity": "sha512-DGIjo79VDEyAnRlfSqYTsy+yoHd2IOjJiKUozD2MV2D85Vso6Bug56mb9tT/fY5Urt0iqk01H7x+llAruDR2zA==" }, "nopt": { "version": "1.0.10", @@ -6810,11 +6561,11 @@ "integrity": "sha1-y480xTIT2JVyP8urkH6UIq28r7E=" }, "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz", + "integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==", "requires": { - "boolbase": "~1.0.0" + "boolbase": "^1.0.0" } }, "num2fraction": { @@ -7056,35 +6807,6 @@ "cyclist": "^1.0.1", "inherits": "^2.0.3", "readable-stream": "^2.1.5" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "param-case": { @@ -7117,11 +6839,16 @@ } }, "parse5": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", - "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", "requires": { - "@types/node": "*" + "parse5": "^6.0.1" } }, "parseurl": { @@ -7843,9 +7570,9 @@ "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==" }, "prismjs": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.22.0.tgz", - "integrity": "sha512-lLJ/Wt9yy0AiSYBf212kK3mM5L8ycwlyTlSxHBAneXLR0nzFMlZ5y7riFPF3E33zXOF2IH95xdY5jIyZbM9z/w==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz", + "integrity": "sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==", "requires": { "clipboard": "^2.0.0" } @@ -8169,13 +7896,17 @@ } }, "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, "readdirp": { @@ -8186,35 +7917,6 @@ "graceful-fs": "^4.1.11", "micromatch": "^3.1.10", "readable-stream": "^2.0.2" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "reduce": { @@ -8280,32 +7982,12 @@ } }, "regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "regexpu-core": { @@ -8343,9 +8025,9 @@ "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" }, "regjsparser": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", - "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.6.tgz", + "integrity": "sha512-jjyuCp+IEMIm3N1H1LLTJW1EISEJV9+5oHdEyrt43Pg9cDSb6rrLZei2cVWpl0xTjmmlpec/lEQGYgM7xfpGCQ==", "requires": { "jsesc": "~0.5.0" }, @@ -8368,15 +8050,109 @@ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, "renderkid": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.4.tgz", - "integrity": "sha512-K2eXrSOJdq+HuKzlcjOlGoOarUu5SDguDEhE7+Ah4zuOWL40j8A/oHvLlLob9PSTNvVnBd+/q0Er1QfpEuem5g==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.5.tgz", + "integrity": "sha512-ccqoLg+HLOHq1vdfYNm4TBeaCDIi1FLt3wGojTDSvdewUv65oTmI3cnT2E4hRjl1gzKZIPK+KZrXzlUYKnR+vQ==", "requires": { - "css-select": "^1.1.0", + "css-select": "^2.0.2", "dom-converter": "^0.2", - "htmlparser2": "^3.3.0", + "htmlparser2": "^3.10.1", "lodash": "^4.17.20", "strip-ansi": "^3.0.0" + }, + "dependencies": { + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==" + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz", + "integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==" + } + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + } + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "requires": { + "boolbase": "~1.0.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "repeat-element": { @@ -8527,9 +8303,9 @@ } }, "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safe-regex": { "version": "1.1.0", @@ -8903,26 +8679,26 @@ } }, "sockjs": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.20.tgz", - "integrity": "sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA==", + "version": "0.3.21", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz", + "integrity": "sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==", "requires": { - "faye-websocket": "^0.10.0", + "faye-websocket": "^0.11.3", "uuid": "^3.4.0", - "websocket-driver": "0.6.5" + "websocket-driver": "^0.7.4" } }, "sockjs-client": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.4.0.tgz", - "integrity": "sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.0.tgz", + "integrity": "sha512-8Dt3BDi4FYNrCFGTL/HtwVzkARrENdwOUf1ZoW/9p3M8lZdFT35jVdrHza+qgxuG9H3/shR4cuX/X9umUrjP8Q==", "requires": { - "debug": "^3.2.5", + "debug": "^3.2.6", "eventsource": "^1.0.7", - "faye-websocket": "~0.11.1", - "inherits": "^2.0.3", - "json3": "^3.3.2", - "url-parse": "^1.4.3" + "faye-websocket": "^0.11.3", + "inherits": "^2.0.4", + "json3": "^3.3.3", + "url-parse": "^1.4.7" }, "dependencies": { "debug": { @@ -8933,14 +8709,6 @@ "ms": "^2.1.1" } }, - "faye-websocket": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", - "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", - "requires": { - "websocket-driver": ">=0.5.1" - } - }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -9044,6 +8812,16 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } } } }, @@ -9162,35 +8940,6 @@ "requires": { "inherits": "~2.0.1", "readable-stream": "^2.0.2" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "stream-each": { @@ -9212,35 +8961,6 @@ "readable-stream": "^2.3.6", "to-arraybuffer": "^1.0.0", "xtend": "^4.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "stream-shift": { @@ -9297,11 +9017,11 @@ } }, "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "safe-buffer": "~5.2.0" + "safe-buffer": "~5.1.0" } }, "strip-ansi": { @@ -9430,6 +9150,27 @@ "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==" }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz", + "integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==" + } + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, "domutils": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", @@ -9446,6 +9187,14 @@ "requires": { "minimist": "^1.2.5" } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "requires": { + "boolbase": "~1.0.0" + } } } }, @@ -9583,35 +9332,6 @@ "requires": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "thunky": { @@ -10031,9 +9751,9 @@ "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=" }, "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "requires": { "punycode": "^2.1.0" } @@ -10215,9 +9935,9 @@ "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==" }, "vue-loader": { - "version": "15.9.5", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.5.tgz", - "integrity": "sha512-oeMOs2b5o5gRqkxfds10bCx6JeXYTwivRgbb8hzOrcThD2z1+GqEKE3EX9A2SGbsYDf4rXwRg6D5n1w0jO5SwA==", + "version": "15.9.6", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.6.tgz", + "integrity": "sha512-j0cqiLzwbeImIC6nVIby2o/ABAWhlppyL/m5oJ67R5MloP0hj/DtFgb0Zmq3J9CG7AJ+AXIvHVnJAPBvrLyuDg==", "requires": { "@vue/component-compiler-utils": "^3.1.0", "hash-sum": "^1.0.2", @@ -10307,12 +10027,12 @@ "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==" }, "vuepress": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/vuepress/-/vuepress-1.7.1.tgz", - "integrity": "sha512-AdA3do1L4DNzeF8sMTE+cSUJ5hR/6f3YujU8DVowi/vFOg/SX2lJF8urvDkZUSXzaAT6aSgkI9L+B6D+i7SJjA==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/vuepress/-/vuepress-1.8.0.tgz", + "integrity": "sha512-YvNitvoEc+JSJRv1W+IoRnvOTFyTWyUMuGuF2kTIbiSwIHb1hNinc3lqNSeBQJy7IBqyEzK5fnTq1mlynh4gwA==", "requires": { - "@vuepress/core": "1.7.1", - "@vuepress/theme-default": "1.7.1", + "@vuepress/core": "1.8.0", + "@vuepress/theme-default": "1.8.0", "cac": "^6.5.6", "envinfo": "^7.2.0", "opencollective-postinstall": "^2.0.2", @@ -10401,9 +10121,9 @@ } }, "vuepress-theme-cosmos": { - "version": "1.0.179", - "resolved": "https://registry.npmjs.org/vuepress-theme-cosmos/-/vuepress-theme-cosmos-1.0.179.tgz", - "integrity": "sha512-BJw/SGn7AmvaSU5Rw74BIRuAkmVZMuf1Gd1++7vpPudgNHEmWSKOHULpIdtkzn1WPXF8sgf4hZQ7+PhESk7JUQ==", + "version": "1.0.180", + "resolved": "https://registry.npmjs.org/vuepress-theme-cosmos/-/vuepress-theme-cosmos-1.0.180.tgz", + "integrity": "sha512-NooA8qCNq/e4fjchOkKtLTaBkPHX1PAfMezP+1ttwezjnHeA1TIccjlqDbq8U7Ath4BXzmcDL5KMX3RtuDARDg==", "requires": { "@cosmos-ui/vue": "^0.35.0", "@vuepress/plugin-google-analytics": "1.7.1", @@ -10452,9 +10172,9 @@ } }, "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "optional": true }, "braces": { @@ -10467,14 +10187,14 @@ } }, "chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", "optional": true, "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", - "fsevents": "~2.1.2", + "fsevents": "~2.3.1", "glob-parent": "~5.1.0", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", @@ -10492,9 +10212,9 @@ } }, "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.1.tgz", + "integrity": "sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==", "optional": true }, "glob-parent": { @@ -10564,9 +10284,9 @@ "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" }, "webpack": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", - "integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==", + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", "requires": { "@webassemblyjs/ast": "1.9.0", "@webassemblyjs/helper-module-context": "1.9.0", @@ -10576,7 +10296,7 @@ "ajv": "^6.10.2", "ajv-keywords": "^3.4.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^4.3.0", + "enhanced-resolve": "^4.5.0", "eslint-scope": "^4.0.3", "json-parse-better-errors": "^1.0.2", "loader-runner": "^2.4.0", @@ -10635,9 +10355,9 @@ } }, "webpack-dev-middleware": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz", - "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==", + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", + "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", "requires": { "memory-fs": "^0.4.1", "mime": "^2.4.4", @@ -10657,9 +10377,9 @@ } }, "webpack-dev-server": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz", - "integrity": "sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg==", + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz", + "integrity": "sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ==", "requires": { "ansi-html": "0.0.7", "bonjour": "^3.5.0", @@ -10681,11 +10401,11 @@ "p-retry": "^3.0.1", "portfinder": "^1.0.26", "schema-utils": "^1.0.0", - "selfsigned": "^1.10.7", + "selfsigned": "^1.10.8", "semver": "^6.3.0", "serve-index": "^1.9.1", - "sockjs": "0.3.20", - "sockjs-client": "1.4.0", + "sockjs": "^0.3.21", + "sockjs-client": "^1.5.0", "spdy": "^4.0.2", "strip-ansi": "^3.0.1", "supports-color": "^6.1.0", @@ -10848,10 +10568,12 @@ } }, "websocket-driver": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", - "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", "websocket-extensions": ">=0.1.1" } }, diff --git a/docs/package.json b/docs/package.json index e4427e8da2fc..4d296f2cc1f0 100644 --- a/docs/package.json +++ b/docs/package.json @@ -14,6 +14,6 @@ "author": "", "license": "ISC", "dependencies": { - "vuepress-theme-cosmos": "^1.0.179" + "vuepress-theme-cosmos": "^1.0.180" } } From ce5db9e4bd14d97e6d4bf5a89572034c49c640a6 Mon Sep 17 00:00:00 2001 From: Marko Date: Mon, 18 Jan 2021 16:41:34 +0100 Subject: [PATCH 045/152] fix proto generation (#8361) * fix proto generation * merge grpc_gateway into gocosmos_out * change env variable names --- .github/workflows/proto-docker.yml | 44 + buf.yaml | 2 + client/grpc/reflection/reflection.pb.gw.go | 88 ++ client/grpc/tmservice/query.pb.gw.go | 236 +++++ contrib/devtools/dockerfile | 21 + docs/core/proto-docs.md | 10 +- scripts/protocgen.sh | 13 +- types/tx/service.pb.gw.go | 169 ++++ x/auth/types/query.pb.gw.go | 88 ++ x/bank/types/query.pb.gw.go | 229 +++++ x/distribution/types/query.pb.gw.go | 417 ++++++++ x/evidence/types/query.pb.gw.go | 95 ++ x/gov/types/query.pb.gw.go | 413 ++++++++ .../transfer/types/query.pb.gw.go | 124 +++ x/ibc/core/02-client/types/query.pb.gw.go | 254 +++++ x/ibc/core/03-connection/types/query.pb.gw.go | 258 +++++ x/ibc/core/04-channel/types/query.pb.gw.go | 945 ++++++++++++++++-- x/mint/types/query.pb.gw.go | 99 ++ x/params/types/proposal/query.pb.gw.go | 48 + x/slashing/types/query.pb.gw.go | 124 +++ x/slashing/types/slashing.pb.go | 15 +- x/staking/types/query.pb.gw.go | 784 ++++++++++++++- x/upgrade/types/query.pb.gw.go | 135 +++ 23 files changed, 4488 insertions(+), 123 deletions(-) create mode 100644 .github/workflows/proto-docker.yml create mode 100644 contrib/devtools/dockerfile diff --git a/.github/workflows/proto-docker.yml b/.github/workflows/proto-docker.yml new file mode 100644 index 000000000000..7e6b5e657644 --- /dev/null +++ b/.github/workflows/proto-docker.yml @@ -0,0 +1,44 @@ +name: Build & Push SDK Proto Builder +on: + push: + branches: + - master + paths: + - "contrib/devtools/dockerfile" + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Prepare + id: prep + run: | + DOCKER_IMAGE=tendermintdev/sdk-proto-gen + VERSION=noop + if [[ $GITHUB_REF == refs/tags/* ]]; then + VERSION=${GITHUB_REF#refs/tags/} + elif [[ $GITHUB_REF == refs/heads/* ]]; then + VERSION=$(echo ${GITHUB_REF#refs/heads/} | sed -r 's#/+#-#g') + if [ "${{ github.event.repository.default_branch }}" = "$VERSION" ]; then + VERSION=latest + fi + fi + TAGS="${DOCKER_IMAGE}:${VERSION}" + echo ::set-output name=tags::${TAGS} + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUBTM_USERNAME }} + password: ${{ secrets.DOCKERHUBTM_TOKEN }} + + - name: Publish to Docker Hub + uses: docker/build-push-action@v2 + with: + context: ./docker-build-sdk-proto + file: ./docker-build-sdk-proto/Dockerfile + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.prep.outputs.tags }} diff --git a/buf.yaml b/buf.yaml index 33388763d7a3..37f716cabaa2 100644 --- a/buf.yaml +++ b/buf.yaml @@ -1,3 +1,5 @@ +version: v1beta1 + build: roots: - proto diff --git a/client/grpc/reflection/reflection.pb.gw.go b/client/grpc/reflection/reflection.pb.gw.go index 255fdd4a794b..ab486750e860 100644 --- a/client/grpc/reflection/reflection.pb.gw.go +++ b/client/grpc/reflection/reflection.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage func request_ReflectionService_ListAllInterfaces_0(ctx context.Context, marshaler runtime.Marshaler, client ReflectionServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq ListAllInterfacesRequest @@ -37,6 +40,15 @@ func request_ReflectionService_ListAllInterfaces_0(ctx context.Context, marshale } +func local_request_ReflectionService_ListAllInterfaces_0(ctx context.Context, marshaler runtime.Marshaler, server ReflectionServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ListAllInterfacesRequest + var metadata runtime.ServerMetadata + + msg, err := server.ListAllInterfaces(ctx, &protoReq) + return msg, metadata, err + +} + func request_ReflectionService_ListImplementations_0(ctx context.Context, marshaler runtime.Marshaler, client ReflectionServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq ListImplementationsRequest var metadata runtime.ServerMetadata @@ -64,6 +76,82 @@ func request_ReflectionService_ListImplementations_0(ctx context.Context, marsha } +func local_request_ReflectionService_ListImplementations_0(ctx context.Context, marshaler runtime.Marshaler, server ReflectionServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ListImplementationsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["interface_name"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "interface_name") + } + + protoReq.InterfaceName, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "interface_name", err) + } + + msg, err := server.ListImplementations(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterReflectionServiceHandlerServer registers the http handlers for service ReflectionService to "mux". +// UnaryRPC :call ReflectionServiceServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterReflectionServiceHandlerFromEndpoint instead. +func RegisterReflectionServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server ReflectionServiceServer) error { + + mux.Handle("GET", pattern_ReflectionService_ListAllInterfaces_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_ReflectionService_ListAllInterfaces_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_ReflectionService_ListAllInterfaces_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_ReflectionService_ListImplementations_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_ReflectionService_ListImplementations_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_ReflectionService_ListImplementations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterReflectionServiceHandlerFromEndpoint is same as RegisterReflectionServiceHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterReflectionServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/client/grpc/tmservice/query.pb.gw.go b/client/grpc/tmservice/query.pb.gw.go index 429583a11a7e..90135d79b937 100644 --- a/client/grpc/tmservice/query.pb.gw.go +++ b/client/grpc/tmservice/query.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage func request_Service_GetNodeInfo_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetNodeInfoRequest @@ -37,6 +40,15 @@ func request_Service_GetNodeInfo_0(ctx context.Context, marshaler runtime.Marsha } +func local_request_Service_GetNodeInfo_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetNodeInfoRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetNodeInfo(ctx, &protoReq) + return msg, metadata, err + +} + func request_Service_GetSyncing_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetSyncingRequest var metadata runtime.ServerMetadata @@ -46,6 +58,15 @@ func request_Service_GetSyncing_0(ctx context.Context, marshaler runtime.Marshal } +func local_request_Service_GetSyncing_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetSyncingRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetSyncing(ctx, &protoReq) + return msg, metadata, err + +} + func request_Service_GetLatestBlock_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetLatestBlockRequest var metadata runtime.ServerMetadata @@ -55,6 +76,15 @@ func request_Service_GetLatestBlock_0(ctx context.Context, marshaler runtime.Mar } +func local_request_Service_GetLatestBlock_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetLatestBlockRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetLatestBlock(ctx, &protoReq) + return msg, metadata, err + +} + func request_Service_GetBlockByHeight_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetBlockByHeightRequest var metadata runtime.ServerMetadata @@ -82,6 +112,33 @@ func request_Service_GetBlockByHeight_0(ctx context.Context, marshaler runtime.M } +func local_request_Service_GetBlockByHeight_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetBlockByHeightRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["height"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "height") + } + + protoReq.Height, err = runtime.Int64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "height", err) + } + + msg, err := server.GetBlockByHeight(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Service_GetLatestValidatorSet_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -102,6 +159,22 @@ func request_Service_GetLatestValidatorSet_0(ctx context.Context, marshaler runt } +func local_request_Service_GetLatestValidatorSet_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetLatestValidatorSetRequest + 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_Service_GetLatestValidatorSet_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GetLatestValidatorSet(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Service_GetValidatorSetByHeight_0 = &utilities.DoubleArray{Encoding: map[string]int{"height": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -140,6 +213,169 @@ func request_Service_GetValidatorSetByHeight_0(ctx context.Context, marshaler ru } +func local_request_Service_GetValidatorSetByHeight_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetValidatorSetByHeightRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["height"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "height") + } + + protoReq.Height, err = runtime.Int64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "height", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Service_GetValidatorSetByHeight_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GetValidatorSetByHeight(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterServiceHandlerServer registers the http handlers for service Service to "mux". +// UnaryRPC :call ServiceServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterServiceHandlerFromEndpoint instead. +func RegisterServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server ServiceServer) error { + + mux.Handle("GET", pattern_Service_GetNodeInfo_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Service_GetNodeInfo_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Service_GetNodeInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Service_GetSyncing_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Service_GetSyncing_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Service_GetSyncing_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Service_GetLatestBlock_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Service_GetLatestBlock_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Service_GetLatestBlock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Service_GetBlockByHeight_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Service_GetBlockByHeight_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Service_GetBlockByHeight_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Service_GetLatestValidatorSet_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Service_GetLatestValidatorSet_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Service_GetLatestValidatorSet_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Service_GetValidatorSetByHeight_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Service_GetValidatorSetByHeight_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Service_GetValidatorSetByHeight_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterServiceHandlerFromEndpoint is same as RegisterServiceHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/contrib/devtools/dockerfile b/contrib/devtools/dockerfile new file mode 100644 index 000000000000..565e66ea330f --- /dev/null +++ b/contrib/devtools/dockerfile @@ -0,0 +1,21 @@ +FROM bufbuild/buf:latest as BUILDER + +FROM golang:alpine + +ENV GOLANG_PROTOBUF_VERSION=1.3.5 \ + GOGO_PROTOBUF_VERSION=1.3.2 \ + GRPC_GATEWAY_VERSION=1.14.7 + + +RUN GO111MODULE=on go get \ + github.com/golang/protobuf/protoc-gen-go@v${GOLANG_PROTOBUF_VERSION} \ + github.com/gogo/protobuf/protoc-gen-gogo@v${GOGO_PROTOBUF_VERSION} \ + github.com/gogo/protobuf/protoc-gen-gogofast@v${GOGO_PROTOBUF_VERSION} \ + github.com/gogo/protobuf/protoc-gen-gogofaster@v${GOGO_PROTOBUF_VERSION} \ + github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway@v${GRPC_GATEWAY_VERSION} \ + github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger@v${GRPC_GATEWAY_VERSION} \ + github.com/regen-network/cosmos-proto/protoc-gen-gocosmos@latest + +RUN GO111MODULE=on go get -u github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc + +COPY --from=BUILDER /usr/local/bin /usr/local/bin diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 912c49fa9401..e8857f2a784a 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -4669,11 +4669,11 @@ liveness activity. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `address` | [string](#string) | | | -| `start_height` | [int64](#int64) | | height at which validator was first a candidate OR was unjailed | -| `index_offset` | [int64](#int64) | | index offset into signed block bit array | -| `jailed_until` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | timestamp validator cannot be unjailed until | -| `tombstoned` | [bool](#bool) | | whether or not a validator has been tombstoned (killed out of validator set) | -| `missed_blocks_counter` | [int64](#int64) | | missed blocks counter (to avoid scanning the array every time) | +| `start_height` | [int64](#int64) | | Height at which validator was first a candidate OR was unjailed | +| `index_offset` | [int64](#int64) | | Index which is incremented each time the validator was a bonded in a block and may have signed a precommit or not. This in conjunction with the `SignedBlocksWindow` param determines the index in the `MissedBlocksBitArray`. | +| `jailed_until` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | Timestamp until which the validator is jailed due to liveness downtime. | +| `tombstoned` | [bool](#bool) | | Whether or not a validator has been tombstoned (killed out of validator set). It is set once the validator commits an equivocation or for any other configured misbehiavor. | +| `missed_blocks_counter` | [int64](#int64) | | A counter kept to avoid unnecessary array reads. Note that `Sum(MissedBlocksBitArray)` always equals `MissedBlocksCounter`. | diff --git a/scripts/protocgen.sh b/scripts/protocgen.sh index f92a47cc9556..bd3e4009712b 100755 --- a/scripts/protocgen.sh +++ b/scripts/protocgen.sh @@ -8,15 +8,10 @@ protoc_gen_gocosmos() { return 1 fi - go get github.com/regen-network/cosmos-proto/protoc-gen-gocosmos 2>/dev/null + go get github.com/regen-network/cosmos-proto/protoc-gen-gocosmos@latest 2>/dev/null } -protoc_gen_doc() { - go get -u github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc 2>/dev/null -} - protoc_gen_gocosmos -protoc_gen_doc proto_dirs=$(find ./proto -path -prune -o -name '*.proto' -print0 | xargs -0 -n1 dirname | sort | uniq) for dir in $proto_dirs; do @@ -25,12 +20,6 @@ for dir in $proto_dirs; do -I "third_party/proto" \ --gocosmos_out=plugins=interfacetype+grpc,\ Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types:. \ - $(find "${dir}" -maxdepth 1 -name '*.proto') - - # command to generate gRPC gateway (*.pb.gw.go in respective modules) files - buf protoc \ - -I "proto" \ - -I "third_party/proto" \ --grpc-gateway_out=logtostderr=true:. \ $(find "${dir}" -maxdepth 1 -name '*.proto') diff --git a/types/tx/service.pb.gw.go b/types/tx/service.pb.gw.go index 59f6e572d9b7..6d94c423ecbd 100644 --- a/types/tx/service.pb.gw.go +++ b/types/tx/service.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage func request_Service_Simulate_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq SimulateRequest @@ -45,6 +48,23 @@ func request_Service_Simulate_0(ctx context.Context, marshaler runtime.Marshaler } +func local_request_Service_Simulate_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SimulateRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Simulate(ctx, &protoReq) + return msg, metadata, err + +} + func request_Service_GetTx_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetTxRequest var metadata runtime.ServerMetadata @@ -72,6 +92,33 @@ func request_Service_GetTx_0(ctx context.Context, marshaler runtime.Marshaler, c } +func local_request_Service_GetTx_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetTxRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["hash"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "hash") + } + + protoReq.Hash, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "hash", err) + } + + msg, err := server.GetTx(ctx, &protoReq) + return msg, metadata, err + +} + func request_Service_BroadcastTx_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq BroadcastTxRequest var metadata runtime.ServerMetadata @@ -89,6 +136,23 @@ func request_Service_BroadcastTx_0(ctx context.Context, marshaler runtime.Marsha } +func local_request_Service_BroadcastTx_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq BroadcastTxRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.BroadcastTx(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Service_GetTxsEvent_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -109,6 +173,111 @@ func request_Service_GetTxsEvent_0(ctx context.Context, marshaler runtime.Marsha } +func local_request_Service_GetTxsEvent_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetTxsEventRequest + 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_Service_GetTxsEvent_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GetTxsEvent(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterServiceHandlerServer registers the http handlers for service Service to "mux". +// UnaryRPC :call ServiceServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterServiceHandlerFromEndpoint instead. +func RegisterServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server ServiceServer) error { + + mux.Handle("POST", pattern_Service_Simulate_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Service_Simulate_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Service_Simulate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Service_GetTx_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Service_GetTx_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Service_GetTx_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_Service_BroadcastTx_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Service_BroadcastTx_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Service_BroadcastTx_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Service_GetTxsEvent_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Service_GetTxsEvent_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Service_GetTxsEvent_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterServiceHandlerFromEndpoint is same as RegisterServiceHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/auth/types/query.pb.gw.go b/x/auth/types/query.pb.gw.go index af50b8afa3c4..0525b9c15364 100644 --- a/x/auth/types/query.pb.gw.go +++ b/x/auth/types/query.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage func request_Query_Account_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryAccountRequest @@ -55,6 +58,33 @@ func request_Query_Account_0(ctx context.Context, marshaler runtime.Marshaler, c } +func local_request_Query_Account_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAccountRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") + } + + protoReq.Address, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) + } + + msg, err := server.Account(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryParamsRequest var metadata runtime.ServerMetadata @@ -64,6 +94,64 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Account_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Account_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Account_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/bank/types/query.pb.gw.go b/x/bank/types/query.pb.gw.go index da70a5cc1995..b1c6372ab7c1 100644 --- a/x/bank/types/query.pb.gw.go +++ b/x/bank/types/query.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage func request_Query_Balance_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryBalanceRequest @@ -66,6 +69,44 @@ func request_Query_Balance_0(ctx context.Context, marshaler runtime.Marshaler, c } +func local_request_Query_Balance_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryBalanceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") + } + + protoReq.Address, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) + } + + val, ok = pathParams["denom"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom") + } + + protoReq.Denom, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err) + } + + msg, err := server.Balance(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_AllBalances_0 = &utilities.DoubleArray{Encoding: map[string]int{"address": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -104,6 +145,40 @@ func request_Query_AllBalances_0(ctx context.Context, marshaler runtime.Marshale } +func local_request_Query_AllBalances_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAllBalancesRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") + } + + protoReq.Address, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_AllBalances_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.AllBalances(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_TotalSupply_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryTotalSupplyRequest var metadata runtime.ServerMetadata @@ -113,6 +188,15 @@ func request_Query_TotalSupply_0(ctx context.Context, marshaler runtime.Marshale } +func local_request_Query_TotalSupply_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryTotalSupplyRequest + var metadata runtime.ServerMetadata + + msg, err := server.TotalSupply(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_SupplyOf_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QuerySupplyOfRequest var metadata runtime.ServerMetadata @@ -140,6 +224,33 @@ func request_Query_SupplyOf_0(ctx context.Context, marshaler runtime.Marshaler, } +func local_request_Query_SupplyOf_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QuerySupplyOfRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["denom"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom") + } + + protoReq.Denom, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err) + } + + msg, err := server.SupplyOf(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryParamsRequest var metadata runtime.ServerMetadata @@ -149,6 +260,124 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Balance_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Balance_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Balance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AllBalances_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_AllBalances_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AllBalances_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_TotalSupply_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_TotalSupply_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_TotalSupply_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_SupplyOf_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_SupplyOf_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_SupplyOf_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/distribution/types/query.pb.gw.go b/x/distribution/types/query.pb.gw.go index 416aee29c94c..7bbe7b7a29fb 100644 --- a/x/distribution/types/query.pb.gw.go +++ b/x/distribution/types/query.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryParamsRequest @@ -37,6 +40,15 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_ValidatorOutstandingRewards_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryValidatorOutstandingRewardsRequest var metadata runtime.ServerMetadata @@ -64,6 +76,33 @@ func request_Query_ValidatorOutstandingRewards_0(ctx context.Context, marshaler } +func local_request_Query_ValidatorOutstandingRewards_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryValidatorOutstandingRewardsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_address") + } + + protoReq.ValidatorAddress, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_address", err) + } + + msg, err := server.ValidatorOutstandingRewards(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_ValidatorCommission_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryValidatorCommissionRequest var metadata runtime.ServerMetadata @@ -91,6 +130,33 @@ func request_Query_ValidatorCommission_0(ctx context.Context, marshaler runtime. } +func local_request_Query_ValidatorCommission_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryValidatorCommissionRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_address") + } + + protoReq.ValidatorAddress, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_address", err) + } + + msg, err := server.ValidatorCommission(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_ValidatorSlashes_0 = &utilities.DoubleArray{Encoding: map[string]int{"validator_address": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -129,6 +195,40 @@ func request_Query_ValidatorSlashes_0(ctx context.Context, marshaler runtime.Mar } +func local_request_Query_ValidatorSlashes_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryValidatorSlashesRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_address") + } + + protoReq.ValidatorAddress, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_address", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ValidatorSlashes_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ValidatorSlashes(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_DelegationRewards_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryDelegationRewardsRequest var metadata runtime.ServerMetadata @@ -167,6 +267,44 @@ func request_Query_DelegationRewards_0(ctx context.Context, marshaler runtime.Ma } +func local_request_Query_DelegationRewards_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDelegationRewardsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["delegator_address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_address") + } + + protoReq.DelegatorAddress, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_address", err) + } + + val, ok = pathParams["validator_address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_address") + } + + protoReq.ValidatorAddress, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_address", err) + } + + msg, err := server.DelegationRewards(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_DelegationTotalRewards_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryDelegationTotalRewardsRequest var metadata runtime.ServerMetadata @@ -194,6 +332,33 @@ func request_Query_DelegationTotalRewards_0(ctx context.Context, marshaler runti } +func local_request_Query_DelegationTotalRewards_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDelegationTotalRewardsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["delegator_address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_address") + } + + protoReq.DelegatorAddress, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_address", err) + } + + msg, err := server.DelegationTotalRewards(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_DelegatorValidators_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryDelegatorValidatorsRequest var metadata runtime.ServerMetadata @@ -221,6 +386,33 @@ func request_Query_DelegatorValidators_0(ctx context.Context, marshaler runtime. } +func local_request_Query_DelegatorValidators_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDelegatorValidatorsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["delegator_address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_address") + } + + protoReq.DelegatorAddress, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_address", err) + } + + msg, err := server.DelegatorValidators(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_DelegatorWithdrawAddress_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryDelegatorWithdrawAddressRequest var metadata runtime.ServerMetadata @@ -248,6 +440,33 @@ func request_Query_DelegatorWithdrawAddress_0(ctx context.Context, marshaler run } +func local_request_Query_DelegatorWithdrawAddress_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDelegatorWithdrawAddressRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["delegator_address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_address") + } + + protoReq.DelegatorAddress, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_address", err) + } + + msg, err := server.DelegatorWithdrawAddress(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_CommunityPool_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryCommunityPoolRequest var metadata runtime.ServerMetadata @@ -257,6 +476,204 @@ func request_Query_CommunityPool_0(ctx context.Context, marshaler runtime.Marsha } +func local_request_Query_CommunityPool_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryCommunityPoolRequest + var metadata runtime.ServerMetadata + + msg, err := server.CommunityPool(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ValidatorOutstandingRewards_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ValidatorOutstandingRewards_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ValidatorOutstandingRewards_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ValidatorCommission_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ValidatorCommission_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ValidatorCommission_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ValidatorSlashes_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ValidatorSlashes_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ValidatorSlashes_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_DelegationRewards_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_DelegationRewards_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DelegationRewards_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_DelegationTotalRewards_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_DelegationTotalRewards_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DelegationTotalRewards_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_DelegatorValidators_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_DelegatorValidators_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DelegatorValidators_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_DelegatorWithdrawAddress_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_DelegatorWithdrawAddress_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DelegatorWithdrawAddress_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_CommunityPool_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_CommunityPool_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_CommunityPool_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/evidence/types/query.pb.gw.go b/x/evidence/types/query.pb.gw.go index 5de488fd9c3f..e15d163524b4 100644 --- a/x/evidence/types/query.pb.gw.go +++ b/x/evidence/types/query.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage func request_Query_Evidence_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryEvidenceRequest @@ -55,6 +58,33 @@ func request_Query_Evidence_0(ctx context.Context, marshaler runtime.Marshaler, } +func local_request_Query_Evidence_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryEvidenceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["evidence_hash"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "evidence_hash") + } + + protoReq.EvidenceHash, err = runtime.Bytes(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "evidence_hash", err) + } + + msg, err := server.Evidence(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_AllEvidence_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -75,6 +105,71 @@ func request_Query_AllEvidence_0(ctx context.Context, marshaler runtime.Marshale } +func local_request_Query_AllEvidence_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAllEvidenceRequest + 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_AllEvidence_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.AllEvidence(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Evidence_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Evidence_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Evidence_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AllEvidence_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_AllEvidence_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AllEvidence_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/gov/types/query.pb.gw.go b/x/gov/types/query.pb.gw.go index 934b33f42d83..52814511b9cb 100644 --- a/x/gov/types/query.pb.gw.go +++ b/x/gov/types/query.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage func request_Query_Proposal_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryProposalRequest @@ -55,6 +58,33 @@ func request_Query_Proposal_0(ctx context.Context, marshaler runtime.Marshaler, } +func local_request_Query_Proposal_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryProposalRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + msg, err := server.Proposal(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_Proposals_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -75,6 +105,22 @@ func request_Query_Proposals_0(ctx context.Context, marshaler runtime.Marshaler, } +func local_request_Query_Proposals_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryProposalsRequest + 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_Proposals_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Proposals(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_Vote_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryVoteRequest var metadata runtime.ServerMetadata @@ -113,6 +159,44 @@ func request_Query_Vote_0(ctx context.Context, marshaler runtime.Marshaler, clie } +func local_request_Query_Vote_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVoteRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + val, ok = pathParams["voter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "voter") + } + + protoReq.Voter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "voter", err) + } + + msg, err := server.Vote(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_Votes_0 = &utilities.DoubleArray{Encoding: map[string]int{"proposal_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -151,6 +235,40 @@ func request_Query_Votes_0(ctx context.Context, marshaler runtime.Marshaler, cli } +func local_request_Query_Votes_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVotesRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Votes_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Votes(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryParamsRequest var metadata runtime.ServerMetadata @@ -178,6 +296,33 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["params_type"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "params_type") + } + + protoReq.ParamsType, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "params_type", err) + } + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_Deposit_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryDepositRequest var metadata runtime.ServerMetadata @@ -216,6 +361,44 @@ func request_Query_Deposit_0(ctx context.Context, marshaler runtime.Marshaler, c } +func local_request_Query_Deposit_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDepositRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + val, ok = pathParams["depositor"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "depositor") + } + + protoReq.Depositor, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "depositor", err) + } + + msg, err := server.Deposit(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_Deposits_0 = &utilities.DoubleArray{Encoding: map[string]int{"proposal_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -254,6 +437,40 @@ func request_Query_Deposits_0(ctx context.Context, marshaler runtime.Marshaler, } +func local_request_Query_Deposits_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDepositsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Deposits_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Deposits(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_TallyResult_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryTallyResultRequest var metadata runtime.ServerMetadata @@ -281,6 +498,202 @@ func request_Query_TallyResult_0(ctx context.Context, marshaler runtime.Marshale } +func local_request_Query_TallyResult_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryTallyResultRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + msg, err := server.TallyResult(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Proposal_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Proposal_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Proposal_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Proposals_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Proposals_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Proposals_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Vote_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Vote_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Vote_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Votes_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Votes_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Votes_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Deposit_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Deposit_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Deposit_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Deposits_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Deposits_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Deposits_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_TallyResult_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_TallyResult_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_TallyResult_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/ibc/applications/transfer/types/query.pb.gw.go b/x/ibc/applications/transfer/types/query.pb.gw.go index 92529fda662e..99a7f1906350 100644 --- a/x/ibc/applications/transfer/types/query.pb.gw.go +++ b/x/ibc/applications/transfer/types/query.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage func request_Query_DenomTrace_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryDenomTraceRequest @@ -55,6 +58,33 @@ func request_Query_DenomTrace_0(ctx context.Context, marshaler runtime.Marshaler } +func local_request_Query_DenomTrace_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDenomTraceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["hash"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "hash") + } + + protoReq.Hash, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "hash", err) + } + + msg, err := server.DenomTrace(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_DenomTraces_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -75,6 +105,22 @@ func request_Query_DenomTraces_0(ctx context.Context, marshaler runtime.Marshale } +func local_request_Query_DenomTraces_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDenomTracesRequest + 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_DenomTraces_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.DenomTraces(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryParamsRequest var metadata runtime.ServerMetadata @@ -84,6 +130,84 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_DenomTrace_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_DenomTrace_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DenomTrace_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_DenomTraces_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_DenomTraces_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DenomTraces_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/ibc/core/02-client/types/query.pb.gw.go b/x/ibc/core/02-client/types/query.pb.gw.go index 529a7b2f3f96..d4414d5ea33b 100644 --- a/x/ibc/core/02-client/types/query.pb.gw.go +++ b/x/ibc/core/02-client/types/query.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage func request_Query_ClientState_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryClientStateRequest @@ -55,6 +58,33 @@ func request_Query_ClientState_0(ctx context.Context, marshaler runtime.Marshale } +func local_request_Query_ClientState_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClientStateRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["client_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "client_id") + } + + protoReq.ClientId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "client_id", err) + } + + msg, err := server.ClientState(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_ClientStates_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -75,6 +105,22 @@ func request_Query_ClientStates_0(ctx context.Context, marshaler runtime.Marshal } +func local_request_Query_ClientStates_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClientStatesRequest + 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_ClientStates_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ClientStates(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_ConsensusState_0 = &utilities.DoubleArray{Encoding: map[string]int{"client_id": 0, "revision_number": 1, "revision_height": 2}, Base: []int{1, 1, 2, 3, 0, 0, 0}, Check: []int{0, 1, 1, 1, 2, 3, 4}} ) @@ -135,6 +181,62 @@ func request_Query_ConsensusState_0(ctx context.Context, marshaler runtime.Marsh } +func local_request_Query_ConsensusState_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryConsensusStateRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["client_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "client_id") + } + + protoReq.ClientId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "client_id", err) + } + + val, ok = pathParams["revision_number"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "revision_number") + } + + protoReq.RevisionNumber, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "revision_number", err) + } + + val, ok = pathParams["revision_height"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "revision_height") + } + + protoReq.RevisionHeight, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "revision_height", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ConsensusState_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ConsensusState(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_ConsensusStates_0 = &utilities.DoubleArray{Encoding: map[string]int{"client_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -173,6 +275,40 @@ func request_Query_ConsensusStates_0(ctx context.Context, marshaler runtime.Mars } +func local_request_Query_ConsensusStates_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryConsensusStatesRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["client_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "client_id") + } + + protoReq.ClientId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "client_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ConsensusStates_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ConsensusStates(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_ClientParams_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryClientParamsRequest var metadata runtime.ServerMetadata @@ -182,6 +318,124 @@ func request_Query_ClientParams_0(ctx context.Context, marshaler runtime.Marshal } +func local_request_Query_ClientParams_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClientParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.ClientParams(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_ClientState_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ClientState_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClientState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ClientStates_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ClientStates_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClientStates_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ConsensusState_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ConsensusState_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ConsensusState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ConsensusStates_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ConsensusStates_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ConsensusStates_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ClientParams_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ClientParams_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClientParams_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/ibc/core/03-connection/types/query.pb.gw.go b/x/ibc/core/03-connection/types/query.pb.gw.go index 95a65726b8b8..3e6de4e06415 100644 --- a/x/ibc/core/03-connection/types/query.pb.gw.go +++ b/x/ibc/core/03-connection/types/query.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage func request_Query_Connection_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryConnectionRequest @@ -55,6 +58,33 @@ func request_Query_Connection_0(ctx context.Context, marshaler runtime.Marshaler } +func local_request_Query_Connection_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryConnectionRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["connection_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "connection_id") + } + + protoReq.ConnectionId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "connection_id", err) + } + + msg, err := server.Connection(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_Connections_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -75,6 +105,22 @@ func request_Query_Connections_0(ctx context.Context, marshaler runtime.Marshale } +func local_request_Query_Connections_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryConnectionsRequest + 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_Connections_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Connections(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_ClientConnections_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryClientConnectionsRequest var metadata runtime.ServerMetadata @@ -102,6 +148,33 @@ func request_Query_ClientConnections_0(ctx context.Context, marshaler runtime.Ma } +func local_request_Query_ClientConnections_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClientConnectionsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["client_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "client_id") + } + + protoReq.ClientId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "client_id", err) + } + + msg, err := server.ClientConnections(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_ConnectionClientState_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryConnectionClientStateRequest var metadata runtime.ServerMetadata @@ -129,6 +202,33 @@ func request_Query_ConnectionClientState_0(ctx context.Context, marshaler runtim } +func local_request_Query_ConnectionClientState_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryConnectionClientStateRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["connection_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "connection_id") + } + + protoReq.ConnectionId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "connection_id", err) + } + + msg, err := server.ConnectionClientState(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_ConnectionConsensusState_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryConnectionConsensusStateRequest var metadata runtime.ServerMetadata @@ -178,6 +278,164 @@ func request_Query_ConnectionConsensusState_0(ctx context.Context, marshaler run } +func local_request_Query_ConnectionConsensusState_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryConnectionConsensusStateRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["connection_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "connection_id") + } + + protoReq.ConnectionId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "connection_id", err) + } + + val, ok = pathParams["revision_number"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "revision_number") + } + + protoReq.RevisionNumber, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "revision_number", err) + } + + val, ok = pathParams["revision_height"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "revision_height") + } + + protoReq.RevisionHeight, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "revision_height", err) + } + + msg, err := server.ConnectionConsensusState(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Connection_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Connection_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Connection_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Connections_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Connections_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Connections_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ClientConnections_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ClientConnections_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClientConnections_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ConnectionClientState_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ConnectionClientState_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ConnectionClientState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ConnectionConsensusState_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ConnectionConsensusState_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ConnectionConsensusState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/ibc/core/04-channel/types/query.pb.gw.go b/x/ibc/core/04-channel/types/query.pb.gw.go index 4fe5bd4399fa..bb5a94aba749 100644 --- a/x/ibc/core/04-channel/types/query.pb.gw.go +++ b/x/ibc/core/04-channel/types/query.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage func request_Query_Channel_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryChannelRequest @@ -66,6 +69,44 @@ func request_Query_Channel_0(ctx context.Context, marshaler runtime.Marshaler, c } +func local_request_Query_Channel_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryChannelRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["channel_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + } + + protoReq.ChannelId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + } + + val, ok = pathParams["port_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") + } + + protoReq.PortId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) + } + + msg, err := server.Channel(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_Channels_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -86,6 +127,22 @@ func request_Query_Channels_0(ctx context.Context, marshaler runtime.Marshaler, } +func local_request_Query_Channels_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryChannelsRequest + 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_Channels_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Channels(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_ConnectionChannels_0 = &utilities.DoubleArray{Encoding: map[string]int{"connection": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -124,6 +181,40 @@ func request_Query_ConnectionChannels_0(ctx context.Context, marshaler runtime.M } +func local_request_Query_ConnectionChannels_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryConnectionChannelsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["connection"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "connection") + } + + protoReq.Connection, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "connection", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ConnectionChannels_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ConnectionChannels(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_ChannelClientState_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryChannelClientStateRequest var metadata runtime.ServerMetadata @@ -162,6 +253,44 @@ func request_Query_ChannelClientState_0(ctx context.Context, marshaler runtime.M } +func local_request_Query_ChannelClientState_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryChannelClientStateRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["channel_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + } + + protoReq.ChannelId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + } + + val, ok = pathParams["port_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") + } + + protoReq.PortId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) + } + + msg, err := server.ChannelClientState(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_ChannelConsensusState_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryChannelConsensusStateRequest var metadata runtime.ServerMetadata @@ -222,8 +351,8 @@ func request_Query_ChannelConsensusState_0(ctx context.Context, marshaler runtim } -func request_Query_PacketCommitment_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPacketCommitmentRequest +func local_request_Query_ChannelConsensusState_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryChannelConsensusStateRequest var metadata runtime.ServerMetadata var ( @@ -255,28 +384,35 @@ func request_Query_PacketCommitment_0(ctx context.Context, marshaler runtime.Mar return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) } - val, ok = pathParams["sequence"] + val, ok = pathParams["revision_number"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sequence") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "revision_number") } - protoReq.Sequence, err = runtime.Uint64(val) + protoReq.RevisionNumber, err = runtime.Uint64(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sequence", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "revision_number", err) } - msg, err := client.PacketCommitment(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + val, ok = pathParams["revision_height"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "revision_height") + } + + protoReq.RevisionHeight, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "revision_height", err) + } + + msg, err := server.ChannelConsensusState(ctx, &protoReq) return msg, metadata, err } -var ( - filter_Query_PacketCommitments_0 = &utilities.DoubleArray{Encoding: map[string]int{"channel_id": 0, "port_id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} -) - -func request_Query_PacketCommitments_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPacketCommitmentsRequest +func request_Query_PacketCommitment_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPacketCommitmentRequest var metadata runtime.ServerMetadata var ( @@ -308,20 +444,24 @@ func request_Query_PacketCommitments_0(ctx context.Context, marshaler runtime.Ma return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) } - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + val, ok = pathParams["sequence"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sequence") } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_PacketCommitments_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + + protoReq.Sequence, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sequence", err) } - msg, err := client.PacketCommitments(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.PacketCommitment(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func request_Query_PacketReceipt_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPacketReceiptRequest +func local_request_Query_PacketCommitment_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPacketCommitmentRequest var metadata runtime.ServerMetadata var ( @@ -364,13 +504,17 @@ func request_Query_PacketReceipt_0(ctx context.Context, marshaler runtime.Marsha return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sequence", err) } - msg, err := client.PacketReceipt(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := server.PacketCommitment(ctx, &protoReq) return msg, metadata, err } -func request_Query_PacketAcknowledgement_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPacketAcknowledgementRequest +var ( + filter_Query_PacketCommitments_0 = &utilities.DoubleArray{Encoding: map[string]int{"channel_id": 0, "port_id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} +) + +func request_Query_PacketCommitments_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPacketCommitmentsRequest var metadata runtime.ServerMetadata var ( @@ -402,28 +546,20 @@ func request_Query_PacketAcknowledgement_0(ctx context.Context, marshaler runtim return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) } - val, ok = pathParams["sequence"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sequence") + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - - protoReq.Sequence, err = runtime.Uint64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sequence", err) + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_PacketCommitments_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.PacketAcknowledgement(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.PacketCommitments(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -var ( - filter_Query_PacketAcknowledgements_0 = &utilities.DoubleArray{Encoding: map[string]int{"channel_id": 0, "port_id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} -) - -func request_Query_PacketAcknowledgements_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPacketAcknowledgementsRequest +func local_request_Query_PacketCommitments_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPacketCommitmentsRequest var metadata runtime.ServerMetadata var ( @@ -458,17 +594,17 @@ func request_Query_PacketAcknowledgements_0(ctx context.Context, marshaler runti if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_PacketAcknowledgements_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_PacketCommitments_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.PacketAcknowledgements(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := server.PacketCommitments(ctx, &protoReq) return msg, metadata, err } -func request_Query_UnreceivedPackets_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryUnreceivedPacketsRequest +func request_Query_PacketReceipt_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPacketReceiptRequest var metadata runtime.ServerMetadata var ( @@ -500,24 +636,24 @@ func request_Query_UnreceivedPackets_0(ctx context.Context, marshaler runtime.Ma return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) } - val, ok = pathParams["packet_commitment_sequences"] + val, ok = pathParams["sequence"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_commitment_sequences") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sequence") } - protoReq.PacketCommitmentSequences, err = runtime.Uint64Slice(val, ",") + protoReq.Sequence, err = runtime.Uint64(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_commitment_sequences", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sequence", err) } - msg, err := client.UnreceivedPackets(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.PacketReceipt(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func request_Query_UnreceivedAcks_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryUnreceivedAcksRequest +func local_request_Query_PacketReceipt_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPacketReceiptRequest var metadata runtime.ServerMetadata var ( @@ -549,24 +685,24 @@ func request_Query_UnreceivedAcks_0(ctx context.Context, marshaler runtime.Marsh return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) } - val, ok = pathParams["packet_ack_sequences"] + val, ok = pathParams["sequence"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_ack_sequences") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sequence") } - protoReq.PacketAckSequences, err = runtime.Uint64Slice(val, ",") + protoReq.Sequence, err = runtime.Uint64(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_ack_sequences", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sequence", err) } - msg, err := client.UnreceivedAcks(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := server.PacketReceipt(ctx, &protoReq) return msg, metadata, err } -func request_Query_NextSequenceReceive_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryNextSequenceReceiveRequest +func request_Query_PacketAcknowledgement_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPacketAcknowledgementRequest var metadata runtime.ServerMetadata var ( @@ -598,11 +734,706 @@ func request_Query_NextSequenceReceive_0(ctx context.Context, marshaler runtime. return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) } - msg, err := client.NextSequenceReceive(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + val, ok = pathParams["sequence"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sequence") + } + + protoReq.Sequence, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sequence", err) + } + + msg, err := client.PacketAcknowledgement(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } +func local_request_Query_PacketAcknowledgement_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPacketAcknowledgementRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["channel_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + } + + protoReq.ChannelId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + } + + val, ok = pathParams["port_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") + } + + protoReq.PortId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) + } + + val, ok = pathParams["sequence"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sequence") + } + + protoReq.Sequence, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sequence", err) + } + + msg, err := server.PacketAcknowledgement(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_PacketAcknowledgements_0 = &utilities.DoubleArray{Encoding: map[string]int{"channel_id": 0, "port_id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} +) + +func request_Query_PacketAcknowledgements_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPacketAcknowledgementsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["channel_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + } + + protoReq.ChannelId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + } + + val, ok = pathParams["port_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") + } + + protoReq.PortId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_PacketAcknowledgements_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.PacketAcknowledgements(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_PacketAcknowledgements_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPacketAcknowledgementsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["channel_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + } + + protoReq.ChannelId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + } + + val, ok = pathParams["port_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") + } + + protoReq.PortId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_PacketAcknowledgements_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.PacketAcknowledgements(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_UnreceivedPackets_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUnreceivedPacketsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["channel_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + } + + protoReq.ChannelId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + } + + val, ok = pathParams["port_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") + } + + protoReq.PortId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) + } + + val, ok = pathParams["packet_commitment_sequences"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_commitment_sequences") + } + + protoReq.PacketCommitmentSequences, err = runtime.Uint64Slice(val, ",") + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_commitment_sequences", err) + } + + msg, err := client.UnreceivedPackets(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_UnreceivedPackets_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUnreceivedPacketsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["channel_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + } + + protoReq.ChannelId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + } + + val, ok = pathParams["port_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") + } + + protoReq.PortId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) + } + + val, ok = pathParams["packet_commitment_sequences"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_commitment_sequences") + } + + protoReq.PacketCommitmentSequences, err = runtime.Uint64Slice(val, ",") + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_commitment_sequences", err) + } + + msg, err := server.UnreceivedPackets(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_UnreceivedAcks_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUnreceivedAcksRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["channel_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + } + + protoReq.ChannelId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + } + + val, ok = pathParams["port_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") + } + + protoReq.PortId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) + } + + val, ok = pathParams["packet_ack_sequences"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_ack_sequences") + } + + protoReq.PacketAckSequences, err = runtime.Uint64Slice(val, ",") + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_ack_sequences", err) + } + + msg, err := client.UnreceivedAcks(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_UnreceivedAcks_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUnreceivedAcksRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["channel_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + } + + protoReq.ChannelId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + } + + val, ok = pathParams["port_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") + } + + protoReq.PortId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) + } + + val, ok = pathParams["packet_ack_sequences"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_ack_sequences") + } + + protoReq.PacketAckSequences, err = runtime.Uint64Slice(val, ",") + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_ack_sequences", err) + } + + msg, err := server.UnreceivedAcks(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_NextSequenceReceive_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryNextSequenceReceiveRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["channel_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + } + + protoReq.ChannelId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + } + + val, ok = pathParams["port_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") + } + + protoReq.PortId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) + } + + msg, err := client.NextSequenceReceive(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_NextSequenceReceive_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryNextSequenceReceiveRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["channel_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + } + + protoReq.ChannelId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + } + + val, ok = pathParams["port_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") + } + + protoReq.PortId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) + } + + msg, err := server.NextSequenceReceive(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Channel_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Channel_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Channel_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Channels_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Channels_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Channels_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ConnectionChannels_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ConnectionChannels_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ConnectionChannels_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ChannelClientState_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ChannelClientState_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ChannelClientState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ChannelConsensusState_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ChannelConsensusState_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ChannelConsensusState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_PacketCommitment_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_PacketCommitment_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_PacketCommitment_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_PacketCommitments_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_PacketCommitments_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_PacketCommitments_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_PacketReceipt_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_PacketReceipt_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_PacketReceipt_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_PacketAcknowledgement_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_PacketAcknowledgement_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_PacketAcknowledgement_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_PacketAcknowledgements_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_PacketAcknowledgements_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_PacketAcknowledgements_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_UnreceivedPackets_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_UnreceivedPackets_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_UnreceivedPackets_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_UnreceivedAcks_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_UnreceivedAcks_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_UnreceivedAcks_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_NextSequenceReceive_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_NextSequenceReceive_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_NextSequenceReceive_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/mint/types/query.pb.gw.go b/x/mint/types/query.pb.gw.go index cda5db851384..c70c3e60b077 100644 --- a/x/mint/types/query.pb.gw.go +++ b/x/mint/types/query.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryParamsRequest @@ -37,6 +40,15 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_Inflation_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryInflationRequest var metadata runtime.ServerMetadata @@ -46,6 +58,15 @@ func request_Query_Inflation_0(ctx context.Context, marshaler runtime.Marshaler, } +func local_request_Query_Inflation_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryInflationRequest + var metadata runtime.ServerMetadata + + msg, err := server.Inflation(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_AnnualProvisions_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryAnnualProvisionsRequest var metadata runtime.ServerMetadata @@ -55,6 +76,84 @@ func request_Query_AnnualProvisions_0(ctx context.Context, marshaler runtime.Mar } +func local_request_Query_AnnualProvisions_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAnnualProvisionsRequest + var metadata runtime.ServerMetadata + + msg, err := server.AnnualProvisions(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Inflation_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Inflation_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Inflation_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AnnualProvisions_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_AnnualProvisions_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AnnualProvisions_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/params/types/proposal/query.pb.gw.go b/x/params/types/proposal/query.pb.gw.go index 9cce0aaaa4bb..c7fab13fca65 100644 --- a/x/params/types/proposal/query.pb.gw.go +++ b/x/params/types/proposal/query.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage var ( filter_Query_Params_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} @@ -48,6 +51,51 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + 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_Params_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/slashing/types/query.pb.gw.go b/x/slashing/types/query.pb.gw.go index 56c0cd19e4c5..083fe73aa9f5 100644 --- a/x/slashing/types/query.pb.gw.go +++ b/x/slashing/types/query.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryParamsRequest @@ -37,6 +40,15 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_SigningInfo_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QuerySigningInfoRequest var metadata runtime.ServerMetadata @@ -64,6 +76,33 @@ func request_Query_SigningInfo_0(ctx context.Context, marshaler runtime.Marshale } +func local_request_Query_SigningInfo_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QuerySigningInfoRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["cons_address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "cons_address") + } + + protoReq.ConsAddress, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "cons_address", err) + } + + msg, err := server.SigningInfo(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_SigningInfos_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -84,6 +123,91 @@ func request_Query_SigningInfos_0(ctx context.Context, marshaler runtime.Marshal } +func local_request_Query_SigningInfos_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QuerySigningInfosRequest + 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_SigningInfos_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.SigningInfos(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_SigningInfo_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_SigningInfo_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_SigningInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_SigningInfos_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_SigningInfos_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_SigningInfos_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/slashing/types/slashing.pb.go b/x/slashing/types/slashing.pb.go index d1607badbd33..2f48e117ebc9 100644 --- a/x/slashing/types/slashing.pb.go +++ b/x/slashing/types/slashing.pb.go @@ -33,16 +33,19 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // liveness activity. type ValidatorSigningInfo struct { Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` - // height at which validator was first a candidate OR was unjailed + // Height at which validator was first a candidate OR was unjailed StartHeight int64 `protobuf:"varint,2,opt,name=start_height,json=startHeight,proto3" json:"start_height,omitempty" yaml:"start_height"` - // index offset into signed block bit array + // Index which is incremented each time the validator was a bonded + // in a block and may have signed a precommit or not. This in conjunction with the + // `SignedBlocksWindow` param determines the index in the `MissedBlocksBitArray`. IndexOffset int64 `protobuf:"varint,3,opt,name=index_offset,json=indexOffset,proto3" json:"index_offset,omitempty" yaml:"index_offset"` - // timestamp validator cannot be unjailed until + // Timestamp until which the validator is jailed due to liveness downtime. JailedUntil time.Time `protobuf:"bytes,4,opt,name=jailed_until,json=jailedUntil,proto3,stdtime" json:"jailed_until" yaml:"jailed_until"` - // whether or not a validator has been tombstoned (killed out of validator - // set) + // Whether or not a validator has been tombstoned (killed out of validator set). It is set + // once the validator commits an equivocation or for any other configured misbehiavor. Tombstoned bool `protobuf:"varint,5,opt,name=tombstoned,proto3" json:"tombstoned,omitempty"` - // missed blocks counter (to avoid scanning the array every time) + // A counter kept to avoid unnecessary array reads. + // Note that `Sum(MissedBlocksBitArray)` always equals `MissedBlocksCounter`. MissedBlocksCounter int64 `protobuf:"varint,6,opt,name=missed_blocks_counter,json=missedBlocksCounter,proto3" json:"missed_blocks_counter,omitempty" yaml:"missed_blocks_counter"` } diff --git a/x/staking/types/query.pb.gw.go b/x/staking/types/query.pb.gw.go index 1d399d8793d6..eecdb3f3168d 100644 --- a/x/staking/types/query.pb.gw.go +++ b/x/staking/types/query.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage var ( filter_Query_Validators_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} @@ -48,6 +51,22 @@ func request_Query_Validators_0(ctx context.Context, marshaler runtime.Marshaler } +func local_request_Query_Validators_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryValidatorsRequest + 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_Validators_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Validators(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_Validator_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryValidatorRequest var metadata runtime.ServerMetadata @@ -75,6 +94,33 @@ func request_Query_Validator_0(ctx context.Context, marshaler runtime.Marshaler, } +func local_request_Query_Validator_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryValidatorRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + } + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + } + + msg, err := server.Validator(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_ValidatorDelegations_0 = &utilities.DoubleArray{Encoding: map[string]int{"validator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -113,6 +159,40 @@ func request_Query_ValidatorDelegations_0(ctx context.Context, marshaler runtime } +func local_request_Query_ValidatorDelegations_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryValidatorDelegationsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + } + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ValidatorDelegations_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ValidatorDelegations(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_ValidatorUnbondingDelegations_0 = &utilities.DoubleArray{Encoding: map[string]int{"validator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -151,6 +231,40 @@ func request_Query_ValidatorUnbondingDelegations_0(ctx context.Context, marshale } +func local_request_Query_ValidatorUnbondingDelegations_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryValidatorUnbondingDelegationsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + } + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ValidatorUnbondingDelegations_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ValidatorUnbondingDelegations(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_Delegation_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryDelegationRequest var metadata runtime.ServerMetadata @@ -189,6 +303,44 @@ func request_Query_Delegation_0(ctx context.Context, marshaler runtime.Marshaler } +func local_request_Query_Delegation_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDelegationRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + } + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + } + + val, ok = pathParams["delegator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_addr") + } + + protoReq.DelegatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_addr", err) + } + + msg, err := server.Delegation(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_UnbondingDelegation_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryUnbondingDelegationRequest var metadata runtime.ServerMetadata @@ -227,6 +379,44 @@ func request_Query_UnbondingDelegation_0(ctx context.Context, marshaler runtime. } +func local_request_Query_UnbondingDelegation_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUnbondingDelegationRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + } + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + } + + val, ok = pathParams["delegator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_addr") + } + + protoReq.DelegatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_addr", err) + } + + msg, err := server.UnbondingDelegation(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_DelegatorDelegations_0 = &utilities.DoubleArray{Encoding: map[string]int{"delegator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) @@ -265,12 +455,8 @@ func request_Query_DelegatorDelegations_0(ctx context.Context, marshaler runtime } -var ( - filter_Query_DelegatorUnbondingDelegations_0 = &utilities.DoubleArray{Encoding: map[string]int{"delegator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} -) - -func request_Query_DelegatorUnbondingDelegations_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDelegatorUnbondingDelegationsRequest +func local_request_Query_DelegatorDelegations_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDelegatorDelegationsRequest var metadata runtime.ServerMetadata var ( @@ -294,21 +480,21 @@ func request_Query_DelegatorUnbondingDelegations_0(ctx context.Context, marshale if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DelegatorUnbondingDelegations_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DelegatorDelegations_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.DelegatorUnbondingDelegations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := server.DelegatorDelegations(ctx, &protoReq) return msg, metadata, err } var ( - filter_Query_Redelegations_0 = &utilities.DoubleArray{Encoding: map[string]int{"delegator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} + filter_Query_DelegatorUnbondingDelegations_0 = &utilities.DoubleArray{Encoding: map[string]int{"delegator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) -func request_Query_Redelegations_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryRedelegationsRequest +func request_Query_DelegatorUnbondingDelegations_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDelegatorUnbondingDelegationsRequest var metadata runtime.ServerMetadata var ( @@ -332,21 +518,17 @@ func request_Query_Redelegations_0(ctx context.Context, marshaler runtime.Marsha if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Redelegations_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DelegatorUnbondingDelegations_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Redelegations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.DelegatorUnbondingDelegations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -var ( - filter_Query_DelegatorValidators_0 = &utilities.DoubleArray{Encoding: map[string]int{"delegator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} -) - -func request_Query_DelegatorValidators_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDelegatorValidatorsRequest +func local_request_Query_DelegatorUnbondingDelegations_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDelegatorUnbondingDelegationsRequest var metadata runtime.ServerMetadata var ( @@ -370,17 +552,21 @@ func request_Query_DelegatorValidators_0(ctx context.Context, marshaler runtime. if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DelegatorValidators_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DelegatorUnbondingDelegations_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.DelegatorValidators(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := server.DelegatorUnbondingDelegations(ctx, &protoReq) return msg, metadata, err } -func request_Query_DelegatorValidator_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryDelegatorValidatorRequest +var ( + filter_Query_Redelegations_0 = &utilities.DoubleArray{Encoding: map[string]int{"delegator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_Redelegations_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryRedelegationsRequest var metadata runtime.ServerMetadata var ( @@ -401,24 +587,20 @@ func request_Query_DelegatorValidator_0(ctx context.Context, marshaler runtime.M return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_addr", err) } - val, ok = pathParams["validator_addr"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - - protoReq.ValidatorAddr, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Redelegations_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.DelegatorValidator(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.Redelegations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func request_Query_HistoricalInfo_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryHistoricalInfoRequest +func local_request_Query_Redelegations_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryRedelegationsRequest var metadata runtime.ServerMetadata var ( @@ -428,28 +610,246 @@ func request_Query_HistoricalInfo_0(ctx context.Context, marshaler runtime.Marsh _ = err ) - val, ok = pathParams["height"] + val, ok = pathParams["delegator_addr"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "height") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_addr") } - protoReq.Height, err = runtime.Int64(val) + protoReq.DelegatorAddr, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "height", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_addr", err) } - msg, err := client.HistoricalInfo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Redelegations_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Redelegations(ctx, &protoReq) return msg, metadata, err } -func request_Query_Pool_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryPoolRequest +var ( + filter_Query_DelegatorValidators_0 = &utilities.DoubleArray{Encoding: map[string]int{"delegator_addr": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_DelegatorValidators_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDelegatorValidatorsRequest var metadata runtime.ServerMetadata - msg, err := client.Pool(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["delegator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_addr") + } + + protoReq.DelegatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_addr", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DelegatorValidators_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.DelegatorValidators(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_DelegatorValidators_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDelegatorValidatorsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["delegator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_addr") + } + + protoReq.DelegatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_addr", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DelegatorValidators_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.DelegatorValidators(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_DelegatorValidator_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDelegatorValidatorRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["delegator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_addr") + } + + protoReq.DelegatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_addr", err) + } + + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + } + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + } + + msg, err := client.DelegatorValidator(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_DelegatorValidator_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDelegatorValidatorRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["delegator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "delegator_addr") + } + + protoReq.DelegatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "delegator_addr", err) + } + + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + } + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + } + + msg, err := server.DelegatorValidator(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_HistoricalInfo_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryHistoricalInfoRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["height"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "height") + } + + protoReq.Height, err = runtime.Int64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "height", err) + } + + msg, err := client.HistoricalInfo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_HistoricalInfo_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryHistoricalInfoRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["height"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "height") + } + + protoReq.Height, err = runtime.Int64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "height", err) + } + + msg, err := server.HistoricalInfo(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Pool_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPoolRequest + var metadata runtime.ServerMetadata + + msg, err := client.Pool(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Pool_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPoolRequest + var metadata runtime.ServerMetadata + + msg, err := server.Pool(ctx, &protoReq) + return msg, metadata, err } @@ -462,6 +862,304 @@ func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, cl } +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Validators_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Validators_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Validators_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Validator_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Validator_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Validator_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ValidatorDelegations_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ValidatorDelegations_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ValidatorDelegations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ValidatorUnbondingDelegations_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ValidatorUnbondingDelegations_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ValidatorUnbondingDelegations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Delegation_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Delegation_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Delegation_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_UnbondingDelegation_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_UnbondingDelegation_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_UnbondingDelegation_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_DelegatorDelegations_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_DelegatorDelegations_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DelegatorDelegations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_DelegatorUnbondingDelegations_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_DelegatorUnbondingDelegations_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DelegatorUnbondingDelegations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Redelegations_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Redelegations_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Redelegations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_DelegatorValidators_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_DelegatorValidators_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DelegatorValidators_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_DelegatorValidator_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_DelegatorValidator_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DelegatorValidator_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_HistoricalInfo_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_HistoricalInfo_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_HistoricalInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Pool_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Pool_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Pool_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Params_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/x/upgrade/types/query.pb.gw.go b/x/upgrade/types/query.pb.gw.go index afccefd1cc01..cf1f9def8eee 100644 --- a/x/upgrade/types/query.pb.gw.go +++ b/x/upgrade/types/query.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage func request_Query_CurrentPlan_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryCurrentPlanRequest @@ -37,6 +40,15 @@ func request_Query_CurrentPlan_0(ctx context.Context, marshaler runtime.Marshale } +func local_request_Query_CurrentPlan_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryCurrentPlanRequest + var metadata runtime.ServerMetadata + + msg, err := server.CurrentPlan(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_AppliedPlan_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryAppliedPlanRequest var metadata runtime.ServerMetadata @@ -64,6 +76,33 @@ func request_Query_AppliedPlan_0(ctx context.Context, marshaler runtime.Marshale } +func local_request_Query_AppliedPlan_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAppliedPlanRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["name"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name") + } + + protoReq.Name, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err) + } + + msg, err := server.AppliedPlan(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_UpgradedConsensusState_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryUpgradedConsensusStateRequest var metadata runtime.ServerMetadata @@ -91,6 +130,102 @@ func request_Query_UpgradedConsensusState_0(ctx context.Context, marshaler runti } +func local_request_Query_UpgradedConsensusState_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUpgradedConsensusStateRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["last_height"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "last_height") + } + + protoReq.LastHeight, err = runtime.Int64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "last_height", err) + } + + msg, err := server.UpgradedConsensusState(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_CurrentPlan_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_CurrentPlan_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_CurrentPlan_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AppliedPlan_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_AppliedPlan_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AppliedPlan_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_UpgradedConsensusState_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_UpgradedConsensusState_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_UpgradedConsensusState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { From d84ca9978889b1e4bbb98f6d6c2a338c02c56d06 Mon Sep 17 00:00:00 2001 From: Tess Rinearson Date: Mon, 18 Jan 2021 17:48:19 +0100 Subject: [PATCH 046/152] simapp: add testnet instructions (#8342) --- simapp/README.md | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 simapp/README.md diff --git a/simapp/README.md b/simapp/README.md new file mode 100644 index 000000000000..fc449f7f2d0a --- /dev/null +++ b/simapp/README.md @@ -0,0 +1,51 @@ +--- +order: false +--- + +# simapp + +simapp is an application built using the Cosmos SDK for testing and educational purposes. + +## Running testnets with `simd` + +If you want to spin up a quick testnet with your friends, you can follow these steps. +Unless otherwise noted, every step must be done by everyone who wants to participate +in this testnet. + +1. `$ make build`. This will build the `simd` binary and install it in your Cosmos SDK repo, + inside a new `build` directory. The following instructions are run from inside + that directory. +2. If you've run `simd` before, you may need to reset your database before starting a new + testnet: `$ ./simd unsafe-reset-all` +3. `$ ./simd init [moniker]`. This will initialize a new working directory, by default at + `~/.simapp`. You need a provide a "moniker," but it doesn't matter what it is. +4. `$ ./simd keys add [key_name]`. This will create a new key, with a name of your choosing. + Save the output of this command somewhere; you'll need the address generated here later. +5. `$ ./simd add-genesis-account $(simd keys show [key_name] -a) [amount]`, where `key_name` + is the same key name as before; and `amount` is something like `10000000000000000000000000stake`. +6. `$ ./simd gentx [key_name] [amount] --chain-id [chain-id]`. This will create the + genesis transaction for your new chain. +7. Now, one person needs to create the genesis file `genesis.json` using the genesis transactions + from every participant, by gathering all the genesis transactions under `config/gentx` and then + calling `./simd collect-gentxs`. This will create a new `genesis.json` file that includes data + from all the validators (we sometimes call it the "super genesis file" to distinguish it from + single-validator genesis files). +8. Once you've received the super genesis file, overwrite your original `genesis.json` file with + the new super `genesis.json`. +9. Modify your `config/config.toml` (in the simapp working directory) to include the other participants as + persistent peers: + + ``` + # Comma separated list of nodes to keep persistent connections to + persistent_peers = "[validator address]@[ip address]:[port],[validator address]@[ip address]:[port]" + ``` + + You can find `validator address` by running `./simd tendermint show-node-id`. (It will be hex-encoded.) + By default, `port` is 26656. +10. Now you can start your nodes: `$ ./simd start`. + +Now you have a small testnet that you can use to try out changes to the Cosmos SDK or Tendermint! + +NOTE: Sometimes creating the network through the `collect-gentxs` will fail, and validators will start +in a funny state (and then panic). If this happens, you can try to create and start the network first +with a single validator and then add additional validators using a `create-validator` transaction. \ No newline at end of file From e8d47bb93b3b8b4d7ea84377ea679d2a85e2fae2 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Mon, 18 Jan 2021 18:00:04 +0100 Subject: [PATCH 047/152] fix: wrappedError.Is (#8355) * fix: wrappedError.Is Is method should return true when used on 2 same errors. * Changelog update Co-authored-by: Alessio Treglia Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- CHANGELOG.md | 8 +++++--- types/errors/errors.go | 5 ++--- types/errors/errors_test.go | 15 +++++++++++---- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bec47aa9bdf0..a23b3dfd3b0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,8 +42,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes - * (x/auth) [\#8287](https://github.com/cosmos/cosmos-sdk/pull/8287) Fix `tx sign --signature-only` to return correct sequence value in signature. - * (x/ibc) [\#8341](https://github.com/cosmos/cosmos-sdk/pull/8341) Fix query latest consensus state. +* (x/auth) [\#8287](https://github.com/cosmos/cosmos-sdk/pull/8287) Fix `tx sign --signature-only` to return correct sequence value in signature. +* (x/ibc) [\#8341](https://github.com/cosmos/cosmos-sdk/pull/8341) Fix query latest consensus state. +* (types/errors) [\#8355][https://github.com/cosmos/cosmos-sdk/pull/8355] Fix errorWrap `Is` method. + ## [v0.40.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0) - 2021-01-08 @@ -201,7 +203,7 @@ sure you are aware of any relevant breaking changes. * (x/slashing) [\#6212](https://github.com/cosmos/cosmos-sdk/pull/6212) Remove `Get*` prefixes from key construction functions * (server) [\#6079](https://github.com/cosmos/cosmos-sdk/pull/6079) Remove `UpgradeOldPrivValFile` (deprecated in Tendermint Core v0.28). * [\#5719](https://github.com/cosmos/cosmos-sdk/pull/5719) Bump Go requirement to 1.14+ - + ### State Machine Breaking diff --git a/types/errors/errors.go b/types/errors/errors.go index d08412524c40..1aa68816ccbf 100644 --- a/types/errors/errors.go +++ b/types/errors/errors.go @@ -318,12 +318,11 @@ func (e *wrappedError) Cause() error { // Is reports whether any error in e's chain matches a target. func (e *wrappedError) Is(target error) bool { - if target == nil { - return e == target + if e == target { + return true } w := e.Cause() - for { if w == target { return true diff --git a/types/errors/errors_test.go b/types/errors/errors_test.go index 7852f8168a7e..ea0e063c3a52 100644 --- a/types/errors/errors_test.go +++ b/types/errors/errors_test.go @@ -161,17 +161,24 @@ func (s *errorsTestSuite) TestWrapEmpty() { } func (s *errorsTestSuite) TestWrappedIs() { + require := s.Require() err := Wrap(ErrTxTooLarge, "context") - s.Require().True(stdlib.Is(err, ErrTxTooLarge)) + require.True(stdlib.Is(err, ErrTxTooLarge)) err = Wrap(err, "more context") - s.Require().True(stdlib.Is(err, ErrTxTooLarge)) + require.True(stdlib.Is(err, ErrTxTooLarge)) err = Wrap(err, "even more context") - s.Require().True(stdlib.Is(err, ErrTxTooLarge)) + require.True(stdlib.Is(err, ErrTxTooLarge)) err = Wrap(ErrInsufficientFee, "...") - s.Require().False(stdlib.Is(err, ErrTxTooLarge)) + require.False(stdlib.Is(err, ErrTxTooLarge)) + + errs := stdlib.New("other") + require.True(stdlib.Is(errs, errs)) + + errw := &wrappedError{"msg", errs} + require.True(errw.Is(errw), "should match itself") } func (s *errorsTestSuite) TestWrappedIsMultiple() { From 01eec66d28e958d797c0773c36d0951cec1dcd8f Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Mon, 18 Jan 2021 15:15:16 -0300 Subject: [PATCH 048/152] x/bank: client denom metadata gRPC (#8317) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: bump tendermint to v0.34.2 * x/bank: denom metadata gRPC * cli: add cmd and tests * gRPC test' * changelog * fix test * Apply suggestions from code review Co-authored-by: Robert Zaremba Co-authored-by: Aditya * fix panic * use cmd.Context() * update tests * Update x/bank/types/errors.go Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> * test fix Co-authored-by: Robert Zaremba Co-authored-by: Aditya Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- CHANGELOG.md | 3 +- docs/architecture/adr-024-coin-metadata.md | 3 +- docs/core/proto-docs.md | 69 + go.sum | 4 - proto/cosmos/bank/v1beta1/query.proto | 39 + x/bank/client/cli/cli_test.go | 168 ++- x/bank/client/cli/query.go | 64 +- x/bank/client/rest/grpc_query_test.go | 103 ++ x/bank/client/rest/query_test.go | 32 +- x/bank/keeper/genesis_test.go | 6 +- x/bank/keeper/grpc_query.go | 52 +- x/bank/keeper/grpc_query_test.go | 180 +++ x/bank/keeper/keeper.go | 10 +- x/bank/keeper/keeper_test.go | 4 +- x/bank/types/errors.go | 9 +- x/bank/types/query.pb.go | 1318 ++++++++++++++++---- x/bank/types/query.pb.gw.go | 178 +++ 17 files changed, 1986 insertions(+), 256 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a23b3dfd3b0d..7d3ef0891128 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,15 +38,16 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (x/bank) [\#8302](https://github.com/cosmos/cosmos-sdk/issues/8302) Add gRPC and CLI queries for client denomination metadata. * (tendermint) [\#8316](https://github.com/cosmos/cosmos-sdk/pull/8316) Bump Tendermint version to [v0.34.2](https://github.com/tendermint/tendermint/releases/tag/v0.34.2) ### Bug Fixes +* (x/bank) [\#8317](https://github.com/cosmos/cosmos-sdk/pull/8317) Fix panic when querying for a not found client denomination metadata. * (x/auth) [\#8287](https://github.com/cosmos/cosmos-sdk/pull/8287) Fix `tx sign --signature-only` to return correct sequence value in signature. * (x/ibc) [\#8341](https://github.com/cosmos/cosmos-sdk/pull/8341) Fix query latest consensus state. * (types/errors) [\#8355][https://github.com/cosmos/cosmos-sdk/pull/8355] Fix errorWrap `Is` method. - ## [v0.40.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0) - 2021-01-08 v0.40.0, known as the Stargate release of the Cosmos SDK, is one of the largest releases diff --git a/docs/architecture/adr-024-coin-metadata.md b/docs/architecture/adr-024-coin-metadata.md index 4f266fa0ec8c..5195a9c40008 100644 --- a/docs/architecture/adr-024-coin-metadata.md +++ b/docs/architecture/adr-024-coin-metadata.md @@ -34,7 +34,7 @@ UX and remove the requirement for making any assumptions on the unit of denomina The `x/bank` module will be updated to store and index metadata by `denom`, specifically the "base" or smallest unit -- the unit the Cosmos SDK state-machine works with. -Metadata may also include a non-zero length list of denominations. Each entry containts the name of +Metadata may also include a non-zero length list of denominations. Each entry contains the name of the denomination `denom`, the exponent to the base and a list of aliases. An entry is to be interpreted as `1 denom = 10^exponent base_denom` (e.g. `1 ETH = 10^18 wei` and `1 uatom = 10^0 uatom`). @@ -92,6 +92,7 @@ As an example, the ATOM's metadata can be defined as follows: ``` Given the above metadata, a client may infer the following things: + - 4.3atom = 4.3 * (10^6) = 4,300,000uatom - The string "atom" can be used as a display name in a list of tokens. - The balance 4300000 can be displayed as 4,300,000uatom or 4,300matom or 4.3atom. diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index e8857f2a784a..d49cf8634bce 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -48,6 +48,10 @@ - [QueryAllBalancesResponse](#cosmos.bank.v1beta1.QueryAllBalancesResponse) - [QueryBalanceRequest](#cosmos.bank.v1beta1.QueryBalanceRequest) - [QueryBalanceResponse](#cosmos.bank.v1beta1.QueryBalanceResponse) + - [QueryDenomMetadataRequest](#cosmos.bank.v1beta1.QueryDenomMetadataRequest) + - [QueryDenomMetadataResponse](#cosmos.bank.v1beta1.QueryDenomMetadataResponse) + - [QueryDenomsMetadataRequest](#cosmos.bank.v1beta1.QueryDenomsMetadataRequest) + - [QueryDenomsMetadataResponse](#cosmos.bank.v1beta1.QueryDenomsMetadataResponse) - [QueryParamsRequest](#cosmos.bank.v1beta1.QueryParamsRequest) - [QueryParamsResponse](#cosmos.bank.v1beta1.QueryParamsResponse) - [QuerySupplyOfRequest](#cosmos.bank.v1beta1.QuerySupplyOfRequest) @@ -1274,6 +1278,69 @@ QueryBalanceResponse is the response type for the Query/Balance RPC method. + + +### QueryDenomMetadataRequest +QueryDenomMetadataRequest is the request type for the Query/DenomMetadata RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `denom` | [string](#string) | | denom is the coin denom to query the metadata for. | + + + + + + + + +### QueryDenomMetadataResponse +QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | | metadata describes and provides all the client information for the requested token. | + + + + + + + + +### QueryDenomsMetadataRequest +QueryDenomsMetadataRequest is the request type for the Query/DenomsMetadata RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + + + + + + + + +### QueryDenomsMetadataResponse +QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `metadatas` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | metadata provides the client information for all the registered tokens. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | + + + + + + ### QueryParamsRequest @@ -1374,6 +1441,8 @@ Query defines the gRPC querier service. | `TotalSupply` | [QueryTotalSupplyRequest](#cosmos.bank.v1beta1.QueryTotalSupplyRequest) | [QueryTotalSupplyResponse](#cosmos.bank.v1beta1.QueryTotalSupplyResponse) | TotalSupply queries the total supply of all coins. | GET|/cosmos/bank/v1beta1/supply| | `SupplyOf` | [QuerySupplyOfRequest](#cosmos.bank.v1beta1.QuerySupplyOfRequest) | [QuerySupplyOfResponse](#cosmos.bank.v1beta1.QuerySupplyOfResponse) | SupplyOf queries the supply of a single coin. | GET|/cosmos/bank/v1beta1/supply/{denom}| | `Params` | [QueryParamsRequest](#cosmos.bank.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.bank.v1beta1.QueryParamsResponse) | Params queries the parameters of x/bank module. | GET|/cosmos/bank/v1beta1/params| +| `DenomMetadata` | [QueryDenomMetadataRequest](#cosmos.bank.v1beta1.QueryDenomMetadataRequest) | [QueryDenomMetadataResponse](#cosmos.bank.v1beta1.QueryDenomMetadataResponse) | DenomsMetadata queries the client metadata of a given coin denomination. | GET|/cosmos/bank/v1beta1/denoms_metadata/{denom}| +| `DenomsMetadata` | [QueryDenomsMetadataRequest](#cosmos.bank.v1beta1.QueryDenomsMetadataRequest) | [QueryDenomsMetadataResponse](#cosmos.bank.v1beta1.QueryDenomsMetadataResponse) | DenomsMetadata queries the client metadata for all registered coin denominations. | GET|/cosmos/bank/v1beta1/denoms_metadata| diff --git a/go.sum b/go.sum index 066d94520d06..30275e7ac493 100644 --- a/go.sum +++ b/go.sum @@ -544,7 +544,6 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -562,7 +561,6 @@ github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2l github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4= github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg= -github.com/tendermint/tendermint v0.34.0 h1:eXCfMgoqVSzrjzOj6clI9GAejcHH0LvOlRjpCmMJksU= github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= github.com/tendermint/tendermint v0.34.2 h1:bB4xReGw4jalTDeNg0npYoONuZrD55F90LrWPF4m/PQ= github.com/tendermint/tendermint v0.34.2/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= @@ -618,7 +616,6 @@ golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9 h1:phUcVbl53swtrUN8kQEXFhUxPlIlWyBfKmidCu7P95o= golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= @@ -797,7 +794,6 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4 h1:Rt0FRalMgdSlXAVJvX4pr65KfqaxHXSLkSJRD9pw6g0= google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f h1:izedQ6yVIc5mZsRuXzmSreCOlzI0lCU1HpG8yEdMiKw= google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= diff --git a/proto/cosmos/bank/v1beta1/query.proto b/proto/cosmos/bank/v1beta1/query.proto index 8f8cfe126330..bc5e29137a95 100644 --- a/proto/cosmos/bank/v1beta1/query.proto +++ b/proto/cosmos/bank/v1beta1/query.proto @@ -35,6 +35,16 @@ service Query { rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { option (google.api.http).get = "/cosmos/bank/v1beta1/params"; } + + // DenomsMetadata queries the client metadata of a given coin denomination. + rpc DenomMetadata(QueryDenomMetadataRequest) returns (QueryDenomMetadataResponse) { + option (google.api.http).get = "/cosmos/bank/v1beta1/denoms_metadata/{denom}"; + } + + // DenomsMetadata queries the client metadata for all registered coin denominations. + rpc DenomsMetadata(QueryDenomsMetadataRequest) returns (QueryDenomsMetadataResponse) { + option (google.api.http).get = "/cosmos/bank/v1beta1/denoms_metadata"; + } } // QueryBalanceRequest is the request type for the Query/Balance RPC method. @@ -109,3 +119,32 @@ message QueryParamsRequest {} message QueryParamsResponse { Params params = 1 [(gogoproto.nullable) = false]; } + +// QueryDenomsMetadataRequest is the request type for the Query/DenomsMetadata RPC method. +message QueryDenomsMetadataRequest { + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 1; +} + +// QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata RPC +// method. +message QueryDenomsMetadataResponse { + // metadata provides the client information for all the registered tokens. + repeated Metadata metadatas = 1 [(gogoproto.nullable) = false]; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + +// QueryDenomMetadataRequest is the request type for the Query/DenomMetadata RPC method. +message QueryDenomMetadataRequest { + // denom is the coin denom to query the metadata for. + string denom = 1; +} + +// QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC +// method. +message QueryDenomMetadataResponse { + // metadata describes and provides all the client information for the requested token. + Metadata metadata = 1 [(gogoproto.nullable) = false]; +} diff --git a/x/bank/client/cli/cli_test.go b/x/bank/client/cli/cli_test.go index a8e94d24569f..952390fe774b 100644 --- a/x/bank/client/cli/cli_test.go +++ b/x/bank/client/cli/cli_test.go @@ -32,12 +32,57 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") cfg := network.DefaultConfig() + genesisState := cfg.GenesisState cfg.NumValidators = 1 + var bankGenesis types.GenesisState + s.Require().NoError(cfg.Codec.UnmarshalJSON(genesisState[types.ModuleName], &bankGenesis)) + + bankGenesis.DenomMetadata = []types.Metadata{ + { + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + { + Denom: "uatom", + Exponent: 0, + Aliases: []string{"microatom"}, + }, + { + Denom: "atom", + Exponent: 6, + Aliases: []string{"ATOM"}, + }, + }, + Base: "uatom", + Display: "atom", + }, + { + Description: "Ethereum mainnet token", + DenomUnits: []*types.DenomUnit{ + { + Denom: "wei", + Exponent: 0, + }, + { + Denom: "eth", + Exponent: 6, + Aliases: []string{"ETH"}, + }, + }, + Base: "wei", + Display: "eth", + }, + } + + bankGenesisBz, err := cfg.Codec.MarshalJSON(&bankGenesis) + s.Require().NoError(err) + genesisState[types.ModuleName] = bankGenesisBz + cfg.GenesisState = genesisState + s.cfg = cfg s.network = network.New(s.T(), cfg) - _, err := s.network.WaitForHeight(1) + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) } @@ -181,6 +226,127 @@ func (s *IntegrationTestSuite) TestGetCmdQueryTotalSupply() { } } +func (s *IntegrationTestSuite) TestGetCmdQueryDenomsMetadata() { + val := s.network.Validators[0] + + testCases := []struct { + name string + args []string + expectErr bool + respType proto.Message + expected proto.Message + }{ + { + name: "all denoms client metadata", + args: []string{ + fmt.Sprintf("--%s=1", flags.FlagHeight), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + respType: &types.QueryDenomsMetadataResponse{}, + expected: &types.QueryDenomsMetadataResponse{ + Metadatas: []types.Metadata{ + { + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + { + Denom: "uatom", + Exponent: 0, + Aliases: []string{"microatom"}, + }, + { + Denom: "atom", + Exponent: 6, + Aliases: []string{"ATOM"}, + }, + }, + Base: "uatom", + Display: "atom", + }, + { + Description: "Ethereum mainnet token", + DenomUnits: []*types.DenomUnit{ + { + Denom: "wei", + Exponent: 0, + Aliases: []string{}, + }, + { + Denom: "eth", + Exponent: 6, + Aliases: []string{"ETH"}, + }, + }, + Base: "wei", + Display: "eth", + }, + }, + Pagination: &query.PageResponse{Total: 2}, + }, + }, + { + name: "client metadata of a specific denomination", + args: []string{ + fmt.Sprintf("--%s=1", flags.FlagHeight), + fmt.Sprintf("--%s=%s", cli.FlagDenom, "uatom"), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + respType: &types.QueryDenomMetadataResponse{}, + expected: &types.QueryDenomMetadataResponse{ + Metadata: types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + { + Denom: "uatom", + Exponent: 0, + Aliases: []string{"microatom"}, + }, + { + Denom: "atom", + Exponent: 6, + Aliases: []string{"ATOM"}, + }, + }, + Base: "uatom", + Display: "atom", + }, + }, + }, + { + name: "client metadata of a bogus denom", + args: []string{ + fmt.Sprintf("--%s=1", flags.FlagHeight), + fmt.Sprintf("--%s=foobar", cli.FlagDenom), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + expectErr: true, + respType: &types.QueryDenomMetadataResponse{}, + expected: &types.QueryDenomMetadataResponse{ + Metadata: types.Metadata{ + DenomUnits: []*types.DenomUnit{}, + }, + }, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdDenomsMetadata() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType)) + s.Require().Equal(tc.expected, tc.respType) + } + }) + } +} + func (s *IntegrationTestSuite) TestNewSendTxCmdGenOnly() { val := s.network.Validators[0] diff --git a/x/bank/client/cli/query.go b/x/bank/client/cli/query.go index 38badd7332d0..fbb9ba43825d 100644 --- a/x/bank/client/cli/query.go +++ b/x/bank/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "strings" @@ -33,6 +32,7 @@ func GetQueryCmd() *cobra.Command { cmd.AddCommand( GetBalancesCmd(), GetCmdQueryTotalSupply(), + GetCmdDenomsMetadata(), ) return cmd @@ -78,7 +78,7 @@ Example: if denom == "" { params := types.NewQueryAllBalancesRequest(addr, pageReq) - res, err := queryClient.AllBalances(context.Background(), params) + res, err := queryClient.AllBalances(cmd.Context(), params) if err != nil { return err } @@ -86,7 +86,7 @@ Example: } params := types.NewQueryBalanceRequest(addr, denom) - res, err := queryClient.Balance(context.Background(), params) + res, err := queryClient.Balance(cmd.Context(), params) if err != nil { return err } @@ -102,6 +102,60 @@ Example: return cmd } +// GetCmdDenomsMetadata defines the cobra command to query client denomination metadata. +func GetCmdDenomsMetadata() *cobra.Command { + cmd := &cobra.Command{ + Use: "denom-metadata", + Short: "Query the client metadata for coin denominations", + Long: strings.TrimSpace( + fmt.Sprintf(`Query the client metadata for all the registered coin denominations + +Example: + To query for the client metadata of all coin denominations use: + $ %s query %s denom-metadata + +To query for the client metadata of a specific coin denomination use: + $ %s query %s denom-metadata --denom=[denom] +`, + version.AppName, types.ModuleName, version.AppName, types.ModuleName, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + denom, err := cmd.Flags().GetString(FlagDenom) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + + if denom == "" { + res, err := queryClient.DenomsMetadata(cmd.Context(), &types.QueryDenomsMetadataRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + } + + res, err := queryClient.DenomMetadata(cmd.Context(), &types.QueryDenomMetadataRequest{Denom: denom}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + cmd.Flags().String(FlagDenom, "", "The specific denomination to query client metadata for") + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + func GetCmdQueryTotalSupply() *cobra.Command { cmd := &cobra.Command{ Use: "total", @@ -131,7 +185,7 @@ To query for the total supply of a specific coin denomination use: queryClient := types.NewQueryClient(clientCtx) if denom == "" { - res, err := queryClient.TotalSupply(context.Background(), &types.QueryTotalSupplyRequest{}) + res, err := queryClient.TotalSupply(cmd.Context(), &types.QueryTotalSupplyRequest{}) if err != nil { return err } @@ -139,7 +193,7 @@ To query for the total supply of a specific coin denomination use: return clientCtx.PrintProto(res) } - res, err := queryClient.SupplyOf(context.Background(), &types.QuerySupplyOfRequest{Denom: denom}) + res, err := queryClient.SupplyOf(cmd.Context(), &types.QuerySupplyOfRequest{Denom: denom}) if err != nil { return err } diff --git a/x/bank/client/rest/grpc_query_test.go b/x/bank/client/rest/grpc_query_test.go index 6274946705ae..d6290a1fef94 100644 --- a/x/bank/client/rest/grpc_query_test.go +++ b/x/bank/client/rest/grpc_query_test.go @@ -98,6 +98,109 @@ func (s *IntegrationTestSuite) TestTotalSupplyGRPCHandler() { } } +func (s *IntegrationTestSuite) TestDenomMetadataGRPCHandler() { + val := s.network.Validators[0] + baseURL := val.APIAddress + + testCases := []struct { + name string + url string + headers map[string]string + expErr bool + respType proto.Message + expected proto.Message + }{ + { + "test GRPC client metadata", + fmt.Sprintf("%s/cosmos/bank/v1beta1/denoms_metadata", baseURL), + map[string]string{ + grpctypes.GRPCBlockHeightHeader: "1", + }, + false, + &types.QueryDenomsMetadataResponse{}, + &types.QueryDenomsMetadataResponse{ + Metadatas: []types.Metadata{ + { + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + { + Denom: "uatom", + Exponent: 0, + Aliases: []string{"microatom"}, + }, + { + Denom: "atom", + Exponent: 6, + Aliases: []string{"ATOM"}, + }, + }, + Base: "uatom", + Display: "atom", + }, + }, + Pagination: &query.PageResponse{Total: 1}, + }, + }, + { + "GRPC client metadata of a specific denom", + fmt.Sprintf("%s/cosmos/bank/v1beta1/denoms_metadata/uatom", baseURL), + map[string]string{ + grpctypes.GRPCBlockHeightHeader: "1", + }, + false, + &types.QueryDenomMetadataResponse{}, + &types.QueryDenomMetadataResponse{ + Metadata: types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + { + Denom: "uatom", + Exponent: 0, + Aliases: []string{"microatom"}, + }, + { + Denom: "atom", + Exponent: 6, + Aliases: []string{"ATOM"}, + }, + }, + Base: "uatom", + Display: "atom", + }, + }, + }, + { + "GRPC client metadata of a bogus denom", + fmt.Sprintf("%s/cosmos/bank/v1beta1/denoms_metadata/foobar", baseURL), + map[string]string{ + grpctypes.GRPCBlockHeightHeader: "1", + }, + true, + &types.QueryDenomMetadataResponse{}, + &types.QueryDenomMetadataResponse{ + Metadata: types.Metadata{ + DenomUnits: []*types.DenomUnit{}, + }, + }, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + resp, err := testutil.GetRequestWithHeaders(tc.url, tc.headers) + s.Require().NoError(err) + + if tc.expErr { + s.Require().Error(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) + } else { + s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) + s.Require().Equal(tc.expected.String(), tc.respType.String()) + } + }) + } +} + func (s *IntegrationTestSuite) TestBalancesGRPCHandler() { val := s.network.Validators[0] baseURL := val.APIAddress diff --git a/x/bank/client/rest/query_test.go b/x/bank/client/rest/query_test.go index 5ca3a15be506..11d731b6dcba 100644 --- a/x/bank/client/rest/query_test.go +++ b/x/bank/client/rest/query_test.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/rest" + "github.com/cosmos/cosmos-sdk/x/bank/types" ) type IntegrationTestSuite struct { @@ -24,12 +25,41 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") cfg := network.DefaultConfig() + genesisState := cfg.GenesisState cfg.NumValidators = 1 + var bankGenesis types.GenesisState + s.Require().NoError(cfg.Codec.UnmarshalJSON(genesisState[types.ModuleName], &bankGenesis)) + + bankGenesis.DenomMetadata = []types.Metadata{ + { + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + { + Denom: "uatom", + Exponent: 0, + Aliases: []string{"microatom"}, + }, + { + Denom: "atom", + Exponent: 6, + Aliases: []string{"ATOM"}, + }, + }, + Base: "uatom", + Display: "atom", + }, + } + + bankGenesisBz, err := cfg.Codec.MarshalJSON(&bankGenesis) + s.Require().NoError(err) + genesisState[types.ModuleName] = bankGenesisBz + cfg.GenesisState = genesisState + s.cfg = cfg s.network = network.New(s.T(), cfg) - _, err := s.network.WaitForHeight(2) + _, err = s.network.WaitForHeight(2) s.Require().NoError(err) } diff --git a/x/bank/keeper/genesis_test.go b/x/bank/keeper/genesis_test.go index bdb8cdc304e1..0e66da54e94d 100644 --- a/x/bank/keeper/genesis_test.go +++ b/x/bank/keeper/genesis_test.go @@ -44,13 +44,13 @@ func (suite *IntegrationTestSuite) getTestBalances() []types.Balance { } func (suite *IntegrationTestSuite) TestInitGenesis() { - require := suite.Require() m := types.Metadata{Description: sdk.DefaultBondDenom, Base: sdk.DefaultBondDenom, Display: sdk.DefaultBondDenom} g := types.DefaultGenesisState() g.DenomMetadata = []types.Metadata{m} bk := suite.app.BankKeeper bk.InitGenesis(suite.ctx, g) - m2 := bk.GetDenomMetaData(suite.ctx, m.Base) - require.Equal(m, m2) + m2, found := bk.GetDenomMetaData(suite.ctx, m.Base) + suite.Require().True(found) + suite.Require().Equal(m, m2) } diff --git a/x/bank/keeper/grpc_query.go b/x/bank/keeper/grpc_query.go index bcf143b8aa14..ae00d1b8734a 100644 --- a/x/bank/keeper/grpc_query.go +++ b/x/bank/keeper/grpc_query.go @@ -61,7 +61,7 @@ func (k BaseKeeper) AllBalances(ctx context.Context, req *types.QueryAllBalances balancesStore := prefix.NewStore(store, types.BalancesPrefix) accountStore := prefix.NewStore(balancesStore, addr.Bytes()) - pageRes, err := query.Paginate(accountStore, req.Pagination, func(key []byte, value []byte) error { + pageRes, err := query.Paginate(accountStore, req.Pagination, func(_, value []byte) error { var result sdk.Coin err := k.cdc.UnmarshalBinaryBare(value, &result) if err != nil { @@ -113,3 +113,53 @@ func (k BaseKeeper) Params(ctx context.Context, req *types.QueryParamsRequest) ( return &types.QueryParamsResponse{Params: params}, nil } + +// DenomsMetadata implements Query/DenomsMetadata gRPC method. +func (k BaseKeeper) DenomsMetadata(c context.Context, req *types.QueryDenomsMetadataRequest) (*types.QueryDenomsMetadataResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(c) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.DenomMetadataPrefix) + + metadatas := []types.Metadata{} + pageRes, err := query.Paginate(store, req.Pagination, func(_, value []byte) error { + var metadata types.Metadata + k.cdc.MustUnmarshalBinaryBare(value, &metadata) + + metadatas = append(metadatas, metadata) + return nil + }) + + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.QueryDenomsMetadataResponse{ + Metadatas: metadatas, + Pagination: pageRes, + }, nil +} + +// DenomMetadata implements Query/DenomMetadata gRPC method. +func (k BaseKeeper) DenomMetadata(c context.Context, req *types.QueryDenomMetadataRequest) (*types.QueryDenomMetadataResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + if req.Denom == "" { + return nil, status.Error(codes.InvalidArgument, "invalid denom") + } + + ctx := sdk.UnwrapSDKContext(c) + + metadata, found := k.GetDenomMetaData(ctx, req.Denom) + if !found { + return nil, status.Errorf(codes.NotFound, "client metadata for denom %s", req.Denom) + } + + return &types.QueryDenomMetadataResponse{ + Metadata: metadata, + }, nil +} diff --git a/x/bank/keeper/grpc_query_test.go b/x/bank/keeper/grpc_query_test.go index 27c29fd9e730..e178f1301751 100644 --- a/x/bank/keeper/grpc_query_test.go +++ b/x/bank/keeper/grpc_query_test.go @@ -4,6 +4,7 @@ package keeper_test import ( gocontext "context" + "fmt" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" @@ -119,3 +120,182 @@ func (suite *IntegrationTestSuite) TestQueryParams() { suite.Require().NotNil(res) suite.Require().Equal(suite.app.BankKeeper.GetParams(suite.ctx), res.GetParams()) } + +func (suite *IntegrationTestSuite) QueryDenomsMetadataRequest() { + var ( + req *types.QueryDenomsMetadataRequest + expMetadata = []types.Metadata{} + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + { + "empty pagination", + func() { + req = &types.QueryDenomsMetadataRequest{} + }, + true, + }, + { + "success, no results", + func() { + req = &types.QueryDenomsMetadataRequest{ + Pagination: &query.PageRequest{ + Limit: 3, + CountTotal: true, + }, + } + }, + true, + }, + { + "success", + func() { + metadataAtom := types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + { + Denom: "uatom", + Exponent: 0, + Aliases: []string{"microatom"}, + }, + { + Denom: "atom", + Exponent: 6, + Aliases: []string{"ATOM"}, + }, + }, + Base: "uatom", + Display: "atom", + } + + metadataEth := types.Metadata{ + Description: "Ethereum native token", + DenomUnits: []*types.DenomUnit{ + { + Denom: "wei", + Exponent: 0, + }, + { + Denom: "eth", + Exponent: 18, + Aliases: []string{"ETH", "ether"}, + }, + }, + Base: "wei", + Display: "eth", + } + + suite.app.BankKeeper.SetDenomMetaData(suite.ctx, metadataAtom) + suite.app.BankKeeper.SetDenomMetaData(suite.ctx, metadataEth) + expMetadata = []types.Metadata{metadataAtom, metadataEth} + req = &types.QueryDenomsMetadataRequest{ + Pagination: &query.PageRequest{ + Limit: 7, + CountTotal: true, + }, + } + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + ctx := sdk.WrapSDKContext(suite.ctx) + + res, err := suite.queryClient.DenomsMetadata(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + suite.Require().Equal(expMetadata, res.Metadatas) + } else { + suite.Require().Error(err) + } + }) + } +} + +func (suite *IntegrationTestSuite) QueryDenomMetadataRequest() { + var ( + req *types.QueryDenomMetadataRequest + expMetadata = types.Metadata{} + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + { + "empty denom", + func() { + req = &types.QueryDenomMetadataRequest{} + }, + false, + }, + { + "not found denom", + func() { + req = &types.QueryDenomMetadataRequest{ + Denom: "foo", + } + }, + false, + }, + { + "success", + func() { + expMetadata := types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + { + Denom: "uatom", + Exponent: 0, + Aliases: []string{"microatom"}, + }, + { + Denom: "atom", + Exponent: 6, + Aliases: []string{"ATOM"}, + }, + }, + Base: "uatom", + Display: "atom", + } + + suite.app.BankKeeper.SetDenomMetaData(suite.ctx, expMetadata) + req = &types.QueryDenomMetadataRequest{ + Denom: expMetadata.Base, + } + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + ctx := sdk.WrapSDKContext(suite.ctx) + + res, err := suite.queryClient.DenomMetadata(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + suite.Require().Equal(expMetadata, res.Metadata) + } else { + suite.Require().Error(err) + } + }) + } +} diff --git a/x/bank/keeper/keeper.go b/x/bank/keeper/keeper.go index 016537221f89..e5f221e4e204 100644 --- a/x/bank/keeper/keeper.go +++ b/x/bank/keeper/keeper.go @@ -27,7 +27,7 @@ type Keeper interface { GetSupply(ctx sdk.Context) exported.SupplyI SetSupply(ctx sdk.Context, supply exported.SupplyI) - GetDenomMetaData(ctx sdk.Context, denom string) types.Metadata + GetDenomMetaData(ctx sdk.Context, denom string) (types.Metadata, bool) SetDenomMetaData(ctx sdk.Context, denomMetaData types.Metadata) IterateAllDenomMetaData(ctx sdk.Context, cb func(types.Metadata) bool) @@ -180,15 +180,19 @@ func (k BaseKeeper) SetSupply(ctx sdk.Context, supply exported.SupplyI) { } // GetDenomMetaData retrieves the denomination metadata -func (k BaseKeeper) GetDenomMetaData(ctx sdk.Context, denom string) types.Metadata { +func (k BaseKeeper) GetDenomMetaData(ctx sdk.Context, denom string) (types.Metadata, bool) { store := ctx.KVStore(k.storeKey) store = prefix.NewStore(store, types.DenomMetadataKey(denom)) bz := store.Get([]byte(denom)) + if bz == nil { + return types.Metadata{}, false + } + var metadata types.Metadata k.cdc.MustUnmarshalBinaryBare(bz, &metadata) - return metadata + return metadata, true } // GetAllDenomMetaData retrieves all denominations metadata diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index 2f5c5055d2c8..80b4b070c278 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -981,8 +981,8 @@ func (suite *IntegrationTestSuite) TestSetDenomMetaData() { app.BankKeeper.SetDenomMetaData(ctx, metadata[i]) } - actualMetadata := app.BankKeeper.GetDenomMetaData(ctx, metadata[1].Base) - + actualMetadata, found := app.BankKeeper.GetDenomMetaData(ctx, metadata[1].Base) + suite.Require().True(found) suite.Require().Equal(metadata[1].GetBase(), actualMetadata.GetBase()) suite.Require().Equal(metadata[1].GetDisplay(), actualMetadata.GetDisplay()) suite.Require().Equal(metadata[1].GetDescription(), actualMetadata.GetDescription()) diff --git a/x/bank/types/errors.go b/x/bank/types/errors.go index dce69d0ac6bf..ab88b40e9b1d 100644 --- a/x/bank/types/errors.go +++ b/x/bank/types/errors.go @@ -6,8 +6,9 @@ import ( // x/bank module sentinel errors var ( - ErrNoInputs = sdkerrors.Register(ModuleName, 2, "no inputs to send transaction") - ErrNoOutputs = sdkerrors.Register(ModuleName, 3, "no outputs to send transaction") - ErrInputOutputMismatch = sdkerrors.Register(ModuleName, 4, "sum inputs != sum outputs") - ErrSendDisabled = sdkerrors.Register(ModuleName, 5, "send transactions are disabled") + ErrNoInputs = sdkerrors.Register(ModuleName, 2, "no inputs to send transaction") + ErrNoOutputs = sdkerrors.Register(ModuleName, 3, "no outputs to send transaction") + ErrInputOutputMismatch = sdkerrors.Register(ModuleName, 4, "sum inputs != sum outputs") + ErrSendDisabled = sdkerrors.Register(ModuleName, 5, "send transactions are disabled") + ErrDenomMetadataNotFound = sdkerrors.Register(ModuleName, 6, "client denom metadata not found") ) diff --git a/x/bank/types/query.pb.go b/x/bank/types/query.pb.go index 8d07c80787fc..c4bedb0098c5 100644 --- a/x/bank/types/query.pb.go +++ b/x/bank/types/query.pb.go @@ -475,6 +475,201 @@ func (m *QueryParamsResponse) GetParams() Params { return Params{} } +// QueryDenomsMetadataRequest is the request type for the Query/DenomsMetadata RPC method. +type QueryDenomsMetadataRequest struct { + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryDenomsMetadataRequest) Reset() { *m = QueryDenomsMetadataRequest{} } +func (m *QueryDenomsMetadataRequest) String() string { return proto.CompactTextString(m) } +func (*QueryDenomsMetadataRequest) ProtoMessage() {} +func (*QueryDenomsMetadataRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_9c6fc1939682df13, []int{10} +} +func (m *QueryDenomsMetadataRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryDenomsMetadataRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryDenomsMetadataRequest.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 *QueryDenomsMetadataRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryDenomsMetadataRequest.Merge(m, src) +} +func (m *QueryDenomsMetadataRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryDenomsMetadataRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryDenomsMetadataRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryDenomsMetadataRequest proto.InternalMessageInfo + +func (m *QueryDenomsMetadataRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata RPC +// method. +type QueryDenomsMetadataResponse struct { + // metadata provides the client information for all the registered tokens. + Metadatas []Metadata `protobuf:"bytes,1,rep,name=metadatas,proto3" json:"metadatas"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryDenomsMetadataResponse) Reset() { *m = QueryDenomsMetadataResponse{} } +func (m *QueryDenomsMetadataResponse) String() string { return proto.CompactTextString(m) } +func (*QueryDenomsMetadataResponse) ProtoMessage() {} +func (*QueryDenomsMetadataResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9c6fc1939682df13, []int{11} +} +func (m *QueryDenomsMetadataResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryDenomsMetadataResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryDenomsMetadataResponse.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 *QueryDenomsMetadataResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryDenomsMetadataResponse.Merge(m, src) +} +func (m *QueryDenomsMetadataResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryDenomsMetadataResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryDenomsMetadataResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryDenomsMetadataResponse proto.InternalMessageInfo + +func (m *QueryDenomsMetadataResponse) GetMetadatas() []Metadata { + if m != nil { + return m.Metadatas + } + return nil +} + +func (m *QueryDenomsMetadataResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryDenomMetadataRequest is the request type for the Query/DenomMetadata RPC method. +type QueryDenomMetadataRequest struct { + // denom is the coin denom to query the metadata for. + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` +} + +func (m *QueryDenomMetadataRequest) Reset() { *m = QueryDenomMetadataRequest{} } +func (m *QueryDenomMetadataRequest) String() string { return proto.CompactTextString(m) } +func (*QueryDenomMetadataRequest) ProtoMessage() {} +func (*QueryDenomMetadataRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_9c6fc1939682df13, []int{12} +} +func (m *QueryDenomMetadataRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryDenomMetadataRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryDenomMetadataRequest.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 *QueryDenomMetadataRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryDenomMetadataRequest.Merge(m, src) +} +func (m *QueryDenomMetadataRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryDenomMetadataRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryDenomMetadataRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryDenomMetadataRequest proto.InternalMessageInfo + +func (m *QueryDenomMetadataRequest) GetDenom() string { + if m != nil { + return m.Denom + } + return "" +} + +// QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC +// method. +type QueryDenomMetadataResponse struct { + // metadata describes and provides all the client information for the requested token. + Metadata Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata"` +} + +func (m *QueryDenomMetadataResponse) Reset() { *m = QueryDenomMetadataResponse{} } +func (m *QueryDenomMetadataResponse) String() string { return proto.CompactTextString(m) } +func (*QueryDenomMetadataResponse) ProtoMessage() {} +func (*QueryDenomMetadataResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9c6fc1939682df13, []int{13} +} +func (m *QueryDenomMetadataResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryDenomMetadataResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryDenomMetadataResponse.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 *QueryDenomMetadataResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryDenomMetadataResponse.Merge(m, src) +} +func (m *QueryDenomMetadataResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryDenomMetadataResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryDenomMetadataResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryDenomMetadataResponse proto.InternalMessageInfo + +func (m *QueryDenomMetadataResponse) GetMetadata() Metadata { + if m != nil { + return m.Metadata + } + return Metadata{} +} + func init() { proto.RegisterType((*QueryBalanceRequest)(nil), "cosmos.bank.v1beta1.QueryBalanceRequest") proto.RegisterType((*QueryBalanceResponse)(nil), "cosmos.bank.v1beta1.QueryBalanceResponse") @@ -486,55 +681,68 @@ func init() { proto.RegisterType((*QuerySupplyOfResponse)(nil), "cosmos.bank.v1beta1.QuerySupplyOfResponse") proto.RegisterType((*QueryParamsRequest)(nil), "cosmos.bank.v1beta1.QueryParamsRequest") proto.RegisterType((*QueryParamsResponse)(nil), "cosmos.bank.v1beta1.QueryParamsResponse") + proto.RegisterType((*QueryDenomsMetadataRequest)(nil), "cosmos.bank.v1beta1.QueryDenomsMetadataRequest") + proto.RegisterType((*QueryDenomsMetadataResponse)(nil), "cosmos.bank.v1beta1.QueryDenomsMetadataResponse") + proto.RegisterType((*QueryDenomMetadataRequest)(nil), "cosmos.bank.v1beta1.QueryDenomMetadataRequest") + proto.RegisterType((*QueryDenomMetadataResponse)(nil), "cosmos.bank.v1beta1.QueryDenomMetadataResponse") } func init() { proto.RegisterFile("cosmos/bank/v1beta1/query.proto", fileDescriptor_9c6fc1939682df13) } var fileDescriptor_9c6fc1939682df13 = []byte{ - // 675 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0x31, 0x6f, 0xd3, 0x40, - 0x14, 0xf6, 0x15, 0x9a, 0x96, 0xcb, 0x76, 0x0d, 0x22, 0x75, 0xc1, 0x41, 0xae, 0xa0, 0x49, 0x69, - 0x7d, 0x24, 0x1d, 0x2a, 0xd8, 0x48, 0x25, 0x18, 0x18, 0x1a, 0x0c, 0x13, 0xdb, 0x25, 0x39, 0x8c, - 0x55, 0xc7, 0xe7, 0xe6, 0x1c, 0x44, 0x54, 0x55, 0x20, 0x24, 0x24, 0x26, 0x40, 0x62, 0x60, 0x60, - 0xe9, 0xcc, 0x2f, 0xe9, 0xc0, 0x50, 0x89, 0x85, 0x09, 0x50, 0x02, 0x12, 0x3f, 0x03, 0xe5, 0xee, - 0x6c, 0x9c, 0xc6, 0x75, 0xb2, 0x30, 0xc5, 0xf7, 0xee, 0xbd, 0xef, 0x7d, 0xdf, 0xbb, 0xef, 0x2e, - 0xb0, 0xd4, 0x62, 0xbc, 0xc3, 0x38, 0x6e, 0x12, 0x7f, 0x0f, 0x3f, 0xab, 0x36, 0x69, 0x48, 0xaa, - 0x78, 0xbf, 0x47, 0xbb, 0x7d, 0x2b, 0xe8, 0xb2, 0x90, 0xa1, 0x25, 0x99, 0x60, 0x8d, 0x12, 0x2c, - 0x95, 0xa0, 0xaf, 0xc7, 0x55, 0x9c, 0xca, 0xec, 0xb8, 0x36, 0x20, 0x8e, 0xeb, 0x93, 0xd0, 0x65, - 0xbe, 0x04, 0xd0, 0x0b, 0x0e, 0x73, 0x98, 0xf8, 0xc4, 0xa3, 0x2f, 0x15, 0xbd, 0xec, 0x30, 0xe6, - 0x78, 0x14, 0x93, 0xc0, 0xc5, 0xc4, 0xf7, 0x59, 0x28, 0x4a, 0xb8, 0xda, 0x35, 0x92, 0xf8, 0x11, - 0x72, 0x8b, 0xb9, 0xfe, 0xc4, 0x7e, 0x82, 0xb5, 0x60, 0x28, 0xf6, 0xcd, 0x5d, 0xb8, 0xf4, 0x60, - 0xc4, 0xaa, 0x4e, 0x3c, 0xe2, 0xb7, 0xa8, 0x4d, 0xf7, 0x7b, 0x94, 0x87, 0xa8, 0x08, 0x17, 0x48, - 0xbb, 0xdd, 0xa5, 0x9c, 0x17, 0xc1, 0x55, 0x50, 0xbe, 0x60, 0x47, 0x4b, 0x54, 0x80, 0xf3, 0x6d, - 0xea, 0xb3, 0x4e, 0x71, 0x4e, 0xc4, 0xe5, 0xe2, 0xf6, 0xe2, 0x9b, 0xa3, 0x92, 0xf6, 0xe7, 0xa8, - 0xa4, 0x99, 0xf7, 0x61, 0x61, 0x1c, 0x90, 0x07, 0xcc, 0xe7, 0x14, 0x6d, 0xc1, 0x85, 0xa6, 0x0c, - 0x09, 0xc4, 0x7c, 0x6d, 0xd9, 0x8a, 0xe7, 0xc5, 0x69, 0x34, 0x2f, 0x6b, 0x87, 0xb9, 0xbe, 0x1d, - 0x65, 0x9a, 0xaf, 0x01, 0xbc, 0x24, 0xd0, 0xee, 0x78, 0x9e, 0x02, 0xe4, 0xd3, 0x29, 0xde, 0x85, - 0xf0, 0xdf, 0x6c, 0x05, 0xcf, 0x7c, 0xed, 0xfa, 0x58, 0x37, 0x79, 0x6c, 0x51, 0xcf, 0x06, 0x71, - 0x22, 0xe1, 0x76, 0xa2, 0x32, 0x21, 0xea, 0x0b, 0x80, 0xc5, 0x49, 0x1e, 0x4a, 0x99, 0x03, 0x17, - 0x15, 0xdf, 0x11, 0x93, 0x73, 0x99, 0xd2, 0xea, 0x37, 0x8f, 0xbf, 0x97, 0xb4, 0xcf, 0x3f, 0x4a, - 0x65, 0xc7, 0x0d, 0x9f, 0xf6, 0x9a, 0x56, 0x8b, 0x75, 0xb0, 0x3a, 0x22, 0xf9, 0xb3, 0xc9, 0xdb, - 0x7b, 0x38, 0xec, 0x07, 0x94, 0x8b, 0x02, 0x6e, 0xc7, 0xe0, 0xe8, 0x5e, 0x8a, 0xae, 0xb5, 0xa9, - 0xba, 0x24, 0xcb, 0xa4, 0x30, 0x73, 0x59, 0x4d, 0xf5, 0x11, 0x0b, 0x89, 0xf7, 0xb0, 0x17, 0x04, - 0x5e, 0x5f, 0xe9, 0x37, 0x5f, 0x28, 0xa1, 0x63, 0x5b, 0x4a, 0x68, 0x0b, 0xe6, 0xb8, 0x88, 0xfc, - 0x0f, 0x99, 0x0a, 0xda, 0xdc, 0x50, 0xfe, 0x91, 0xbd, 0x77, 0x9f, 0x44, 0xc7, 0x1d, 0xfb, 0x0e, - 0x24, 0x7c, 0x67, 0x36, 0xe0, 0xc5, 0x53, 0xd9, 0x8a, 0xeb, 0x36, 0xcc, 0x91, 0x0e, 0xeb, 0xf9, - 0xe1, 0x54, 0xb7, 0xd5, 0xcf, 0x8f, 0xb8, 0xda, 0x2a, 0xdd, 0x2c, 0x40, 0x24, 0x10, 0x1b, 0xa4, - 0x4b, 0x3a, 0x91, 0xd9, 0xcc, 0x86, 0xba, 0x26, 0x51, 0x54, 0x75, 0xb9, 0x05, 0x73, 0x81, 0x88, - 0xa8, 0x2e, 0x2b, 0x56, 0xca, 0x1b, 0x60, 0xc9, 0xa2, 0xa8, 0x8f, 0x2c, 0xa8, 0xfd, 0x9e, 0x87, - 0xf3, 0x02, 0x12, 0x7d, 0x04, 0x70, 0x41, 0x99, 0x0a, 0x95, 0x53, 0x01, 0x52, 0x6e, 0xa8, 0x5e, - 0x99, 0x21, 0x53, 0xb2, 0x34, 0xb7, 0x5f, 0x7d, 0xfd, 0xf5, 0x61, 0xae, 0x8a, 0x30, 0x4e, 0x7f, - 0x0c, 0xa4, 0xbd, 0xf0, 0x81, 0xba, 0x3f, 0x87, 0xf8, 0x40, 0x0c, 0xf7, 0x10, 0x7d, 0x02, 0x30, - 0x9f, 0x70, 0x3c, 0xda, 0x38, 0xbb, 0xe7, 0xe4, 0x05, 0xd5, 0x37, 0x67, 0xcc, 0x56, 0x2c, 0xb1, - 0x60, 0x59, 0x41, 0x6b, 0x33, 0xb2, 0x44, 0xef, 0x00, 0xcc, 0x27, 0x6c, 0x9a, 0xc5, 0x6e, 0xd2, - 0xe8, 0x59, 0xec, 0x52, 0xbc, 0x6f, 0xae, 0x0a, 0x76, 0x57, 0xd0, 0x4a, 0x2a, 0x3b, 0xe9, 0x5d, - 0xf4, 0x16, 0xc0, 0xc5, 0xc8, 0x89, 0x28, 0xe3, 0x80, 0x4e, 0x79, 0x5b, 0x5f, 0x9f, 0x25, 0x55, - 0x11, 0xb9, 0x21, 0x88, 0x5c, 0x43, 0xab, 0x19, 0x44, 0xe2, 0x03, 0x7c, 0x09, 0x60, 0x4e, 0xba, - 0x0f, 0xad, 0x9d, 0xdd, 0x63, 0xcc, 0xea, 0x7a, 0x79, 0x7a, 0xe2, 0x4c, 0x33, 0x91, 0x3e, 0xaf, - 0xef, 0x1c, 0x0f, 0x0c, 0x70, 0x32, 0x30, 0xc0, 0xcf, 0x81, 0x01, 0xde, 0x0f, 0x0d, 0xed, 0x64, - 0x68, 0x68, 0xdf, 0x86, 0x86, 0xf6, 0xb8, 0x92, 0xf9, 0x36, 0x3c, 0x97, 0x68, 0xe2, 0x89, 0x68, - 0xe6, 0xc4, 0x9f, 0xd5, 0xd6, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x31, 0x99, 0x37, 0x9b, 0x84, - 0x07, 0x00, 0x00, + // 824 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xcf, 0x6b, 0x13, 0x5b, + 0x14, 0xce, 0xed, 0x7b, 0x4d, 0xd3, 0x13, 0xde, 0x5b, 0xdc, 0xe6, 0xf1, 0xd2, 0xe9, 0x6b, 0xf2, + 0x98, 0x6a, 0x9b, 0xd6, 0x74, 0xa6, 0x69, 0x85, 0xa2, 0x1b, 0x69, 0x2a, 0xba, 0x10, 0x69, 0x8c, + 0xae, 0x04, 0x91, 0x9b, 0x64, 0x1c, 0x43, 0x93, 0xb9, 0xd3, 0xdc, 0x89, 0x58, 0x4a, 0x51, 0x04, + 0xc1, 0x95, 0x0a, 0x2e, 0x5c, 0xb8, 0xa9, 0x1b, 0x41, 0x97, 0xfe, 0x15, 0x5d, 0xb8, 0x28, 0xb8, + 0x71, 0xa5, 0xd2, 0xba, 0xf0, 0xcf, 0x90, 0xdc, 0x1f, 0xd3, 0x49, 0x32, 0x4d, 0x06, 0xd1, 0x55, + 0x66, 0xee, 0x3d, 0xe7, 0x3b, 0xdf, 0x77, 0xee, 0xb9, 0xdf, 0x04, 0xb2, 0x55, 0xca, 0x9a, 0x94, + 0x99, 0x15, 0xe2, 0x6c, 0x9a, 0xf7, 0x0a, 0x15, 0xcb, 0x23, 0x05, 0x73, 0xab, 0x6d, 0xb5, 0xb6, + 0x0d, 0xb7, 0x45, 0x3d, 0x8a, 0x27, 0x44, 0x80, 0xd1, 0x09, 0x30, 0x64, 0x80, 0xb6, 0xe0, 0x67, + 0x31, 0x4b, 0x44, 0xfb, 0xb9, 0x2e, 0xb1, 0xeb, 0x0e, 0xf1, 0xea, 0xd4, 0x11, 0x00, 0x5a, 0xca, + 0xa6, 0x36, 0xe5, 0x8f, 0x66, 0xe7, 0x49, 0xae, 0xfe, 0x67, 0x53, 0x6a, 0x37, 0x2c, 0x93, 0xb8, + 0x75, 0x93, 0x38, 0x0e, 0xf5, 0x78, 0x0a, 0x93, 0xbb, 0x99, 0x20, 0xbe, 0x42, 0xae, 0xd2, 0xba, + 0xd3, 0xb7, 0x1f, 0x60, 0xcd, 0x19, 0xf2, 0x7d, 0x7d, 0x03, 0x26, 0xae, 0x75, 0x58, 0x15, 0x49, + 0x83, 0x38, 0x55, 0xab, 0x6c, 0x6d, 0xb5, 0x2d, 0xe6, 0xe1, 0x34, 0x8c, 0x91, 0x5a, 0xad, 0x65, + 0x31, 0x96, 0x46, 0xff, 0xa3, 0xdc, 0x78, 0x59, 0xbd, 0xe2, 0x14, 0x8c, 0xd6, 0x2c, 0x87, 0x36, + 0xd3, 0x23, 0x7c, 0x5d, 0xbc, 0x9c, 0x4f, 0x3c, 0xd9, 0xcb, 0xc6, 0xbe, 0xef, 0x65, 0x63, 0xfa, + 0x15, 0x48, 0x75, 0x03, 0x32, 0x97, 0x3a, 0xcc, 0xc2, 0x2b, 0x30, 0x56, 0x11, 0x4b, 0x1c, 0x31, + 0xb9, 0x3c, 0x69, 0xf8, 0xfd, 0x62, 0x96, 0xea, 0x97, 0xb1, 0x4e, 0xeb, 0x4e, 0x59, 0x45, 0xea, + 0x8f, 0x11, 0xfc, 0xcb, 0xd1, 0xd6, 0x1a, 0x0d, 0x09, 0xc8, 0x86, 0x53, 0xbc, 0x04, 0x70, 0xdc, + 0x5b, 0xce, 0x33, 0xb9, 0x3c, 0xdb, 0x55, 0x4d, 0x1c, 0x9b, 0xaa, 0x59, 0x22, 0xb6, 0x12, 0x5e, + 0x0e, 0x64, 0x06, 0x44, 0x7d, 0x40, 0x90, 0xee, 0xe7, 0x21, 0x95, 0xd9, 0x90, 0x90, 0x7c, 0x3b, + 0x4c, 0xfe, 0x18, 0x28, 0xad, 0xb8, 0xb4, 0xff, 0x39, 0x1b, 0x7b, 0xf7, 0x25, 0x9b, 0xb3, 0xeb, + 0xde, 0xdd, 0x76, 0xc5, 0xa8, 0xd2, 0xa6, 0x29, 0x8f, 0x48, 0xfc, 0x2c, 0xb2, 0xda, 0xa6, 0xe9, + 0x6d, 0xbb, 0x16, 0xe3, 0x09, 0xac, 0xec, 0x83, 0xe3, 0xcb, 0x21, 0xba, 0xe6, 0x86, 0xea, 0x12, + 0x2c, 0x83, 0xc2, 0xf4, 0x49, 0xd9, 0xd5, 0x1b, 0xd4, 0x23, 0x8d, 0xeb, 0x6d, 0xd7, 0x6d, 0x6c, + 0x4b, 0xfd, 0xfa, 0x03, 0x29, 0xb4, 0x6b, 0x4b, 0x0a, 0xad, 0x42, 0x9c, 0xf1, 0x95, 0xdf, 0x21, + 0x53, 0x42, 0xeb, 0x79, 0x39, 0x3f, 0xa2, 0xf6, 0xc6, 0x1d, 0x75, 0xdc, 0xfe, 0xdc, 0xa1, 0xc0, + 0xdc, 0xe9, 0x25, 0xf8, 0xa7, 0x27, 0x5a, 0x72, 0x5d, 0x85, 0x38, 0x69, 0xd2, 0xb6, 0xe3, 0x0d, + 0x9d, 0xb6, 0xe2, 0x9f, 0x1d, 0xae, 0x65, 0x19, 0xae, 0xa7, 0x00, 0x73, 0xc4, 0x12, 0x69, 0x91, + 0xa6, 0x1a, 0x36, 0xbd, 0x24, 0xaf, 0x89, 0x5a, 0x95, 0x55, 0xce, 0x41, 0xdc, 0xe5, 0x2b, 0xb2, + 0xca, 0x94, 0x11, 0xe2, 0x01, 0x86, 0x48, 0x52, 0x75, 0x44, 0x82, 0x5e, 0x03, 0x8d, 0x23, 0x5e, + 0xec, 0xe8, 0x60, 0x57, 0x2d, 0x8f, 0xd4, 0x88, 0x47, 0x94, 0xda, 0xee, 0x11, 0x46, 0x3f, 0x3b, + 0xc2, 0xfa, 0x5b, 0x04, 0x53, 0xa1, 0x65, 0xa4, 0x80, 0x35, 0x18, 0x6f, 0xca, 0x35, 0x35, 0xbc, + 0xd3, 0xa1, 0x1a, 0x54, 0xa6, 0x54, 0x71, 0x9c, 0xf5, 0xeb, 0xa6, 0xb2, 0x00, 0x93, 0xc7, 0x54, + 0x7b, 0x1b, 0x12, 0x7e, 0xfc, 0xb7, 0x82, 0x4d, 0xec, 0x13, 0x77, 0x01, 0x12, 0x8a, 0xa6, 0x6c, + 0x61, 0x24, 0x6d, 0x7e, 0xd2, 0xf2, 0xfb, 0x04, 0x8c, 0x72, 0x7c, 0xfc, 0x12, 0xc1, 0x98, 0xbc, + 0xf8, 0x38, 0x17, 0x0a, 0x12, 0xe2, 0xa2, 0xda, 0x7c, 0x84, 0x48, 0xc1, 0x55, 0x5f, 0x7d, 0xf4, + 0xf1, 0xdb, 0x8b, 0x91, 0x02, 0x36, 0xcd, 0x70, 0xc3, 0x16, 0x16, 0x60, 0xee, 0x48, 0x8f, 0xdb, + 0x35, 0x77, 0x78, 0x07, 0x76, 0xf1, 0x2b, 0x04, 0xc9, 0x80, 0x2b, 0xe1, 0xfc, 0xc9, 0x35, 0xfb, + 0x4d, 0x54, 0x5b, 0x8c, 0x18, 0x2d, 0x59, 0x9a, 0x9c, 0xe5, 0x3c, 0x9e, 0x8b, 0xc8, 0x12, 0x3f, + 0x43, 0x90, 0x0c, 0x58, 0xc9, 0x20, 0x76, 0xfd, 0x66, 0x34, 0x88, 0x5d, 0x88, 0x3f, 0xe9, 0x33, + 0x9c, 0xdd, 0x34, 0x9e, 0x0a, 0x65, 0x27, 0xfc, 0x05, 0x3f, 0x45, 0x90, 0x50, 0x6e, 0x81, 0x07, + 0x1c, 0x50, 0x8f, 0xff, 0x68, 0x0b, 0x51, 0x42, 0x25, 0x91, 0x33, 0x9c, 0xc8, 0x69, 0x3c, 0x33, + 0x80, 0x88, 0x7f, 0x80, 0x0f, 0x11, 0xc4, 0x85, 0x43, 0xe0, 0xb9, 0x93, 0x6b, 0x74, 0xd9, 0x91, + 0x96, 0x1b, 0x1e, 0x18, 0xa9, 0x27, 0xc2, 0x8b, 0xf0, 0x1b, 0x04, 0x7f, 0x75, 0x5d, 0x21, 0x6c, + 0x9c, 0x5c, 0x20, 0xec, 0x7a, 0x6a, 0x66, 0xe4, 0x78, 0xc9, 0xeb, 0x2c, 0xe7, 0x65, 0xe0, 0x7c, + 0x28, 0x2f, 0xde, 0x1a, 0x76, 0x5b, 0x5d, 0x44, 0xbf, 0x57, 0xaf, 0x11, 0xfc, 0xdd, 0xed, 0x64, + 0x78, 0x58, 0xe5, 0x5e, 0x6b, 0xd5, 0x96, 0xa2, 0x27, 0x48, 0xae, 0x79, 0xce, 0x75, 0x16, 0x9f, + 0x8a, 0xc2, 0xb5, 0xb8, 0xbe, 0x7f, 0x98, 0x41, 0x07, 0x87, 0x19, 0xf4, 0xf5, 0x30, 0x83, 0x9e, + 0x1f, 0x65, 0x62, 0x07, 0x47, 0x99, 0xd8, 0xa7, 0xa3, 0x4c, 0xec, 0xe6, 0xfc, 0xc0, 0x8f, 0xe1, + 0x7d, 0x01, 0xcb, 0xbf, 0x89, 0x95, 0x38, 0xff, 0x77, 0xb6, 0xf2, 0x23, 0x00, 0x00, 0xff, 0xff, + 0xb4, 0xd4, 0xb0, 0xfc, 0x75, 0x0a, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -559,6 +767,10 @@ type QueryClient interface { SupplyOf(ctx context.Context, in *QuerySupplyOfRequest, opts ...grpc.CallOption) (*QuerySupplyOfResponse, error) // Params queries the parameters of x/bank module. Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) + // DenomsMetadata queries the client metadata of a given coin denomination. + DenomMetadata(ctx context.Context, in *QueryDenomMetadataRequest, opts ...grpc.CallOption) (*QueryDenomMetadataResponse, error) + // DenomsMetadata queries the client metadata for all registered coin denominations. + DenomsMetadata(ctx context.Context, in *QueryDenomsMetadataRequest, opts ...grpc.CallOption) (*QueryDenomsMetadataResponse, error) } type queryClient struct { @@ -614,6 +826,24 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts . return out, nil } +func (c *queryClient) DenomMetadata(ctx context.Context, in *QueryDenomMetadataRequest, opts ...grpc.CallOption) (*QueryDenomMetadataResponse, error) { + out := new(QueryDenomMetadataResponse) + err := c.cc.Invoke(ctx, "/cosmos.bank.v1beta1.Query/DenomMetadata", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) DenomsMetadata(ctx context.Context, in *QueryDenomsMetadataRequest, opts ...grpc.CallOption) (*QueryDenomsMetadataResponse, error) { + out := new(QueryDenomsMetadataResponse) + err := c.cc.Invoke(ctx, "/cosmos.bank.v1beta1.Query/DenomsMetadata", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // Balance queries the balance of a single coin for a single account. @@ -626,6 +856,10 @@ type QueryServer interface { SupplyOf(context.Context, *QuerySupplyOfRequest) (*QuerySupplyOfResponse, error) // Params queries the parameters of x/bank module. Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) + // DenomsMetadata queries the client metadata of a given coin denomination. + DenomMetadata(context.Context, *QueryDenomMetadataRequest) (*QueryDenomMetadataResponse, error) + // DenomsMetadata queries the client metadata for all registered coin denominations. + DenomsMetadata(context.Context, *QueryDenomsMetadataRequest) (*QueryDenomsMetadataResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -647,6 +881,12 @@ func (*UnimplementedQueryServer) SupplyOf(ctx context.Context, req *QuerySupplyO func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") } +func (*UnimplementedQueryServer) DenomMetadata(ctx context.Context, req *QueryDenomMetadataRequest) (*QueryDenomMetadataResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DenomMetadata not implemented") +} +func (*UnimplementedQueryServer) DenomsMetadata(ctx context.Context, req *QueryDenomsMetadataRequest) (*QueryDenomsMetadataResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DenomsMetadata not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -742,6 +982,42 @@ func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interf return interceptor(ctx, in, info, handler) } +func _Query_DenomMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryDenomMetadataRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).DenomMetadata(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.bank.v1beta1.Query/DenomMetadata", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).DenomMetadata(ctx, req.(*QueryDenomMetadataRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_DenomsMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryDenomsMetadataRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).DenomsMetadata(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.bank.v1beta1.Query/DenomsMetadata", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).DenomsMetadata(ctx, req.(*QueryDenomsMetadataRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "cosmos.bank.v1beta1.Query", HandlerType: (*QueryServer)(nil), @@ -766,6 +1042,14 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "Params", Handler: _Query_Params_Handler, }, + { + MethodName: "DenomMetadata", + Handler: _Query_DenomMetadata_Handler, + }, + { + MethodName: "DenomsMetadata", + Handler: _Query_DenomsMetadata_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "cosmos/bank/v1beta1/query.proto", @@ -1113,81 +1397,228 @@ func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { - offset -= sovQuery(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *QueryBalanceRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Address) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.Denom) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) +func (m *QueryDenomsMetadataRequest) 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 n + return dAtA[:n], nil } -func (m *QueryBalanceResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Balance != nil { - l = m.Balance.Size() - n += 1 + l + sovQuery(uint64(l)) - } - return n +func (m *QueryDenomsMetadataRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryAllBalancesRequest) Size() (n int) { - if m == nil { - return 0 - } +func (m *QueryDenomsMetadataRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - l = len(m.Address) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } if m.Pagination != nil { - l = m.Pagination.Size() - n += 1 + l + sovQuery(uint64(l)) + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa } - return n + return len(dAtA) - i, nil } -func (m *QueryAllBalancesResponse) Size() (n int) { - if m == nil { - return 0 +func (m *QueryDenomsMetadataResponse) 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 *QueryDenomsMetadataResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryDenomsMetadataResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - if len(m.Balances) > 0 { - for _, e := range m.Balances { - l = e.Size() - n += 1 + l + sovQuery(uint64(l)) - } - } if m.Pagination != nil { - l = m.Pagination.Size() - n += 1 + l + sovQuery(uint64(l)) - } - return n + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Metadatas) > 0 { + for iNdEx := len(m.Metadatas) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Metadatas[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 *QueryDenomMetadataRequest) 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 *QueryDenomMetadataRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryDenomMetadataRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryDenomMetadataResponse) 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 *QueryDenomMetadataResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryDenomMetadataResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Metadata.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 encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryBalanceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryBalanceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Balance != nil { + l = m.Balance.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAllBalancesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAllBalancesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Balances) > 0 { + for _, e := range m.Balances { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n } func (m *QueryTotalSupplyRequest) Size() (n int) { @@ -1258,6 +1689,62 @@ func (m *QueryParamsResponse) Size() (n int) { return n } +func (m *QueryDenomsMetadataRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryDenomsMetadataResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Metadatas) > 0 { + for _, e := range m.Metadatas { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryDenomMetadataRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryDenomMetadataResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Metadata.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1352,11 +1839,385 @@ func (m *QueryBalanceRequest) Unmarshal(dAtA []byte) error { if postIndex < 0 { return ErrInvalidLengthQuery } - if postIndex > l { + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryBalanceResponse) 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: QueryBalanceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryBalanceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Balance", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Balance == nil { + m.Balance = &types.Coin{} + } + if err := m.Balance.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAllBalancesRequest) 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: QueryAllBalancesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAllBalancesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAllBalancesResponse) 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: QueryAllBalancesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAllBalancesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Balances", 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.Balances = append(m.Balances, types.Coin{}) + if err := m.Balances[len(m.Balances)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryTotalSupplyRequest) 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 } - m.Denom = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex + 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: QueryTotalSupplyRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryTotalSupplyRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -1378,7 +2239,7 @@ func (m *QueryBalanceRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryBalanceResponse) Unmarshal(dAtA []byte) error { +func (m *QueryTotalSupplyResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1401,15 +2262,15 @@ func (m *QueryBalanceResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryBalanceResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryTotalSupplyResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryBalanceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryTotalSupplyResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Balance", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Supply", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1436,10 +2297,8 @@ func (m *QueryBalanceResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Balance == nil { - m.Balance = &types.Coin{} - } - if err := m.Balance.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Supply = append(m.Supply, types.Coin{}) + if err := m.Supply[len(m.Supply)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -1464,7 +2323,7 @@ func (m *QueryBalanceResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryAllBalancesRequest) Unmarshal(dAtA []byte) error { +func (m *QuerySupplyOfRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1487,15 +2346,15 @@ func (m *QueryAllBalancesRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryAllBalancesRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QuerySupplyOfRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryAllBalancesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QuerySupplyOfRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1523,43 +2382,7 @@ func (m *QueryAllBalancesRequest) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Address = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Pagination == nil { - m.Pagination = &query.PageRequest{} - } - if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Denom = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -1582,7 +2405,7 @@ func (m *QueryAllBalancesRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryAllBalancesResponse) Unmarshal(dAtA []byte) error { +func (m *QuerySupplyOfResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1605,49 +2428,15 @@ func (m *QueryAllBalancesResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryAllBalancesResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QuerySupplyOfResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryAllBalancesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QuerySupplyOfResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Balances", 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.Balances = append(m.Balances, types.Coin{}) - if err := m.Balances[len(m.Balances)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1674,10 +2463,7 @@ func (m *QueryAllBalancesResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Pagination == nil { - m.Pagination = &query.PageResponse{} - } - if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -1702,7 +2488,7 @@ func (m *QueryAllBalancesResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryTotalSupplyRequest) Unmarshal(dAtA []byte) error { +func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1725,10 +2511,10 @@ func (m *QueryTotalSupplyRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryTotalSupplyRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryParamsRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryTotalSupplyRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -1752,7 +2538,7 @@ func (m *QueryTotalSupplyRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryTotalSupplyResponse) Unmarshal(dAtA []byte) error { +func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1775,15 +2561,15 @@ func (m *QueryTotalSupplyResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryTotalSupplyResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryParamsResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryTotalSupplyResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Supply", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1810,8 +2596,7 @@ func (m *QueryTotalSupplyResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Supply = append(m.Supply, types.Coin{}) - if err := m.Supply[len(m.Supply)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -1836,7 +2621,7 @@ func (m *QueryTotalSupplyResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QuerySupplyOfRequest) Unmarshal(dAtA []byte) error { +func (m *QueryDenomsMetadataRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1859,17 +2644,17 @@ func (m *QuerySupplyOfRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QuerySupplyOfRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryDenomsMetadataRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QuerySupplyOfRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryDenomsMetadataRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -1879,23 +2664,27 @@ func (m *QuerySupplyOfRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLengthQuery } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthQuery } if postIndex > l { return io.ErrUnexpectedEOF } - m.Denom = string(dAtA[iNdEx:postIndex]) + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex default: iNdEx = preIndex @@ -1918,7 +2707,7 @@ func (m *QuerySupplyOfRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QuerySupplyOfResponse) Unmarshal(dAtA []byte) error { +func (m *QueryDenomsMetadataResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1941,15 +2730,15 @@ func (m *QuerySupplyOfResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QuerySupplyOfResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryDenomsMetadataResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QuerySupplyOfResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryDenomsMetadataResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Metadatas", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1976,7 +2765,44 @@ func (m *QuerySupplyOfResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Metadatas = append(m.Metadatas, Metadata{}) + if err := m.Metadatas[len(m.Metadatas)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -2001,7 +2827,7 @@ func (m *QuerySupplyOfResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { +func (m *QueryDenomMetadataRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2024,12 +2850,44 @@ func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryParamsRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryDenomMetadataRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryDenomMetadataRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -2051,7 +2909,7 @@ func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { +func (m *QueryDenomMetadataResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2074,15 +2932,15 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryParamsResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryDenomMetadataResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryDenomMetadataResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -2109,7 +2967,7 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Metadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/x/bank/types/query.pb.gw.go b/x/bank/types/query.pb.gw.go index b1c6372ab7c1..06c7e2d04aa5 100644 --- a/x/bank/types/query.pb.gw.go +++ b/x/bank/types/query.pb.gw.go @@ -269,6 +269,96 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal } +func request_Query_DenomMetadata_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDenomMetadataRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["denom"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom") + } + + protoReq.Denom, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err) + } + + msg, err := client.DenomMetadata(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_DenomMetadata_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDenomMetadataRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["denom"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom") + } + + protoReq.Denom, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err) + } + + msg, err := server.DenomMetadata(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_DenomsMetadata_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_DenomsMetadata_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDenomsMetadataRequest + 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_DenomsMetadata_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.DenomsMetadata(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_DenomsMetadata_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDenomsMetadataRequest + 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_DenomsMetadata_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.DenomsMetadata(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -375,6 +465,46 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_DenomMetadata_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_DenomMetadata_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DenomMetadata_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_DenomsMetadata_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_DenomsMetadata_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DenomsMetadata_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -516,6 +646,46 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_DenomMetadata_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_DenomMetadata_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_DenomMetadata_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_DenomsMetadata_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_DenomsMetadata_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_DenomsMetadata_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -529,6 +699,10 @@ var ( pattern_Query_SupplyOf_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "bank", "v1beta1", "supply", "denom"}, "", runtime.AssumeColonVerbOpt(true))) pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "bank", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_DenomMetadata_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "bank", "v1beta1", "denoms_metadata", "denom"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_DenomsMetadata_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "bank", "v1beta1", "denoms_metadata"}, "", runtime.AssumeColonVerbOpt(true))) ) var ( @@ -541,4 +715,8 @@ var ( forward_Query_SupplyOf_0 = runtime.ForwardResponseMessage forward_Query_Params_0 = runtime.ForwardResponseMessage + + forward_Query_DenomMetadata_0 = runtime.ForwardResponseMessage + + forward_Query_DenomsMetadata_0 = runtime.ForwardResponseMessage ) From b771effc6c755d553ffefc39f4e6bae8aa082a79 Mon Sep 17 00:00:00 2001 From: MD Aleem <72057206+aleem1314@users.noreply.github.com> Date: Mon, 18 Jan 2021 23:55:22 +0530 Subject: [PATCH 049/152] gRPC-web proxy (#8077) * init * WIP config * WIP add proxy server * fmt * WIP * setup proxy server * clean go.mod * lint * lint * lint * custom codec * lint * add comments * change grpc-proxy port * add grpc-web * update server/start.go * add tests * add test with client * Update server/start.go Co-authored-by: Anil Kumar Kammari * Update server/start.go Co-authored-by: Amaury * Update server/start.go Co-authored-by: Amaury * review changes * review changes * Update server/start.go Co-authored-by: Anil Kumar Kammari Co-authored-by: Amaury Co-authored-by: Aleksandr Bezobchuk Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- go.mod | 2 + go.sum | 9 + server/config/config.go | 23 ++- server/config/toml.go | 13 ++ server/grpc/grpc_web.go | 25 +++ server/grpc/grpc_web_test.go | 313 +++++++++++++++++++++++++++++++++++ server/start.go | 25 ++- testutil/network/network.go | 17 +- testutil/network/util.go | 18 ++ 9 files changed, 438 insertions(+), 7 deletions(-) create mode 100644 server/grpc/grpc_web.go create mode 100644 server/grpc/grpc_web_test.go diff --git a/go.mod b/go.mod index 10577caa095a..c507219f9663 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/iavl v0.15.3 github.com/cosmos/ledger-cosmos-go v0.11.1 + github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dgraph-io/ristretto v0.0.3 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 @@ -26,6 +27,7 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/hashicorp/golang-lru v0.5.4 + github.com/improbable-eng/grpc-web v0.13.0 github.com/magiconair/properties v1.8.4 github.com/mattn/go-isatty v0.0.12 github.com/otiai10/copy v1.4.2 diff --git a/go.sum b/go.sum index 30275e7ac493..aeab76d9c9e3 100644 --- a/go.sum +++ b/go.sum @@ -123,6 +123,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/dgraph-io/badger/v2 v2.2007.1/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= github.com/dgraph-io/badger/v2 v2.2007.2 h1:EjjK0KqwaFMlPin1ajhP943VPENHJdEz1KLIegjaI3k= github.com/dgraph-io/badger/v2 v2.2007.2/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= @@ -253,6 +255,7 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de github.com/grpc-ecosystem/go-grpc-middleware v1.2.1/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= @@ -299,6 +302,8 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/improbable-eng/grpc-web v0.13.0 h1:7XqtaBWaOCH0cVGKHyvhtcuo6fgW32Y10yRKrDHFHOc= +github.com/improbable-eng/grpc-web v0.13.0/go.mod h1:6hRR09jOEG81ADP5wCQju1z71g6OL4eEvELdran/3cs= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= @@ -308,6 +313,7 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -327,6 +333,7 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -373,6 +380,7 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= @@ -500,6 +508,7 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= diff --git a/server/config/config.go b/server/config/config.go index 80e79f04558d..68f6cf4352f6 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -14,8 +14,11 @@ import ( const ( defaultMinGasPrices = "" - // DefaultGRPCAddress is the default address the gRPC server binds to. + // DefaultGRPCAddress defines the default address to bind the gRPC server to. DefaultGRPCAddress = "0.0.0.0:9090" + + // DefaultGRPCWebAddress defines the default address to bind the gRPC-web server to. + DefaultGRPCWebAddress = "0.0.0.0:9091" ) // BaseConfig defines the server's basic configuration @@ -107,6 +110,15 @@ type GRPCConfig struct { Address string `mapstructure:"address"` } +// GRPCWebConfig defines configuration for the gRPC-web server. +type GRPCWebConfig struct { + // Enable defines if the gRPC-web should be enabled. + Enable bool `mapstructure:"enable"` + + // Address defines the gRPC-web server to listen on + Address string `mapstructure:"address"` +} + // StateSyncConfig defines the state sync snapshot configuration. type StateSyncConfig struct { // SnapshotInterval sets the interval at which state sync snapshots are taken. @@ -126,6 +138,7 @@ type Config struct { Telemetry telemetry.Config `mapstructure:"telemetry"` API APIConfig `mapstructure:"api"` GRPC GRPCConfig `mapstructure:"grpc"` + GRPCWeb GRPCWebConfig `mapstructure:"grpc-web"` StateSync StateSyncConfig `mapstructure:"state-sync"` } @@ -185,6 +198,10 @@ func DefaultConfig() *Config { Enable: true, Address: DefaultGRPCAddress, }, + GRPCWeb: GRPCWebConfig{ + Enable: true, + Address: DefaultGRPCWebAddress, + }, StateSync: StateSyncConfig{ SnapshotInterval: 0, SnapshotKeepRecent: 2, @@ -239,6 +256,10 @@ func GetConfig(v *viper.Viper) Config { Enable: v.GetBool("grpc.enable"), Address: v.GetString("grpc.address"), }, + GRPCWeb: GRPCWebConfig{ + Enable: v.GetBool("grpc-web.enable"), + Address: v.GetString("grpc-web.address"), + }, StateSync: StateSyncConfig{ SnapshotInterval: v.GetUint64("state-sync.snapshot-interval"), SnapshotKeepRecent: v.GetUint32("state-sync.snapshot-keep-recent"), diff --git a/server/config/toml.go b/server/config/toml.go index b042da74293d..58dc7bfed2b4 100644 --- a/server/config/toml.go +++ b/server/config/toml.go @@ -147,6 +147,19 @@ enable = {{ .GRPC.Enable }} # Address defines the gRPC server address to bind to. address = "{{ .GRPC.Address }}" +############################################################################### +### gRPC Web Configuration ### +############################################################################### + +[grpc-web] + +# GRPCWebEnable defines if the gRPC-web should be enabled. +# NOTE: gRPC must also be enabled, otherwise, this configuration is a no-op. +enable = {{ .GRPCWeb.Enable }} + +# Address defines the gRPC-web server address to bind to. +address = "{{ .GRPCWeb.Address }}" + ############################################################################### ### State Sync Configuration ### ############################################################################### diff --git a/server/grpc/grpc_web.go b/server/grpc/grpc_web.go new file mode 100644 index 000000000000..30c71808e43e --- /dev/null +++ b/server/grpc/grpc_web.go @@ -0,0 +1,25 @@ +package grpc + +import ( + "net/http" + + "github.com/cosmos/cosmos-sdk/server/config" + "github.com/improbable-eng/grpc-web/go/grpcweb" + "google.golang.org/grpc" +) + +// StartGRPCWeb starts a gRPC-Web server on the given address. +func StartGRPCWeb(grpcSrv *grpc.Server, config config.Config) (*http.Server, error) { + wrappedServer := grpcweb.WrapServer(grpcSrv) + handler := func(resp http.ResponseWriter, req *http.Request) { + wrappedServer.ServeHTTP(resp, req) + } + grpcWebSrv := &http.Server{ + Addr: config.GRPCWeb.Address, + Handler: http.HandlerFunc(handler), + } + if err := grpcWebSrv.ListenAndServe(); err != nil { + return nil, err + } + return grpcWebSrv, nil +} diff --git a/server/grpc/grpc_web_test.go b/server/grpc/grpc_web_test.go new file mode 100644 index 000000000000..8f563becc666 --- /dev/null +++ b/server/grpc/grpc_web_test.go @@ -0,0 +1,313 @@ +package grpc_test + +import ( + "bufio" + "bytes" + "encoding/base64" + "encoding/binary" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/textproto" + "strconv" + "strings" + "testing" + + "github.com/golang/protobuf/proto" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "google.golang.org/grpc/codes" + + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" + "github.com/cosmos/cosmos-sdk/codec" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/testutil/network" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +// https://github.com/improbable-eng/grpc-web/blob/master/go/grpcweb/wrapper_test.go used as a reference +// to setup grpcRequest config. + +const grpcWebContentType = "application/grpc-web" + +type GRPCWebTestSuite struct { + suite.Suite + + cfg network.Config + network *network.Network + protoCdc *codec.ProtoCodec +} + +func (s *GRPCWebTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + s.cfg = cfg + s.network = network.New(s.T(), s.cfg) + s.Require().NotNil(s.network) + + _, err := s.network.WaitForHeight(2) + s.Require().NoError(err) + + s.protoCdc = codec.NewProtoCodec(s.cfg.InterfaceRegistry) +} + +func (s *GRPCWebTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +func (s *GRPCWebTestSuite) Test_Latest_Validators() { + val := s.network.Validators[0] + for _, contentType := range []string{grpcWebContentType} { + headers, trailers, responses, err := s.makeGrpcRequest( + "/cosmos.base.tendermint.v1beta1.Service/GetLatestValidatorSet", + headerWithFlag(), + serializeProtoMessages([]proto.Message{&tmservice.GetLatestValidatorSetRequest{}}), false) + + s.Require().NoError(err) + s.Require().Equal(1, len(responses)) + s.assertTrailerGrpcCode(trailers, codes.OK, "") + s.assertContentTypeSet(headers, contentType) + var valsSet tmservice.GetLatestValidatorSetResponse + err = s.protoCdc.UnmarshalBinaryBare(responses[0], &valsSet) + s.Require().NoError(err) + pubKey, ok := valsSet.Validators[0].PubKey.GetCachedValue().(cryptotypes.PubKey) + s.Require().Equal(true, ok) + s.Require().Equal(pubKey, val.PubKey) + } +} + +func (s *GRPCWebTestSuite) Test_Total_Supply() { + for _, contentType := range []string{grpcWebContentType} { + headers, trailers, responses, err := s.makeGrpcRequest( + "/cosmos.bank.v1beta1.Query/TotalSupply", + headerWithFlag(), + serializeProtoMessages([]proto.Message{&banktypes.QueryTotalSupplyRequest{}}), false) + + s.Require().NoError(err) + s.Require().Equal(1, len(responses)) + s.assertTrailerGrpcCode(trailers, codes.OK, "") + s.assertContentTypeSet(headers, contentType) + var totalSupply banktypes.QueryTotalSupplyResponse + _ = s.protoCdc.UnmarshalBinaryBare(responses[0], &totalSupply) + } +} + +func (s *GRPCWebTestSuite) assertContentTypeSet(headers http.Header, contentType string) { + s.Require().Equal(contentType, headers.Get("content-type"), `Expected there to be content-type=%v`, contentType) +} + +func (s *GRPCWebTestSuite) assertTrailerGrpcCode(trailers Trailer, code codes.Code, desc string) { + s.Require().NotEmpty(trailers.Get("grpc-status"), "grpc-status must not be empty in trailers") + statusCode, err := strconv.Atoi(trailers.Get("grpc-status")) + s.Require().NoError(err, "no error parsing grpc-status") + s.Require().EqualValues(code, statusCode, "grpc-status must match expected code") + s.Require().EqualValues(desc, trailers.Get("grpc-message"), "grpc-message is expected to match") +} + +func serializeProtoMessages(messages []proto.Message) [][]byte { + out := [][]byte{} + for _, m := range messages { + b, _ := proto.Marshal(m) + out = append(out, b) + } + return out +} + +func (s *GRPCWebTestSuite) makeRequest( + verb string, method string, headers http.Header, body io.Reader, isText bool, +) (*http.Response, error) { + val := s.network.Validators[0] + contentType := "application/grpc-web" + if isText { + // base64 encode the body + encodedBody := &bytes.Buffer{} + encoder := base64.NewEncoder(base64.StdEncoding, encodedBody) + _, err := io.Copy(encoder, body) + if err != nil { + return nil, err + } + err = encoder.Close() + if err != nil { + return nil, err + } + body = encodedBody + contentType = "application/grpc-web-text" + } + + url := fmt.Sprintf("http://%s%s", val.AppConfig.GRPCWeb.Address, method) + req, err := http.NewRequest(verb, url, body) + s.Require().NoError(err, "failed creating a request") + req.Header = headers + + req.Header.Set("Content-Type", contentType) + client := &http.Client{} + resp, err := client.Do(req) + return resp, err +} + +func decodeMultipleBase64Chunks(b []byte) ([]byte, error) { + // grpc-web allows multiple base64 chunks: the implementation may send base64-encoded + // "chunks" with potential padding whenever the runtime needs to flush a byte buffer. + // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md + output := make([]byte, base64.StdEncoding.DecodedLen(len(b))) + outputEnd := 0 + + for inputEnd := 0; inputEnd < len(b); { + chunk := b[inputEnd:] + paddingIndex := bytes.IndexByte(chunk, '=') + if paddingIndex != -1 { + // find the consecutive = + for { + paddingIndex += 1 + if paddingIndex >= len(chunk) || chunk[paddingIndex] != '=' { + break + } + } + chunk = chunk[:paddingIndex] + } + inputEnd += len(chunk) + + n, err := base64.StdEncoding.Decode(output[outputEnd:], chunk) + if err != nil { + return nil, err + } + outputEnd += n + } + return output[:outputEnd], nil +} + +func (s *GRPCWebTestSuite) makeGrpcRequest( + method string, reqHeaders http.Header, requestMessages [][]byte, isText bool, +) (headers http.Header, trailers Trailer, responseMessages [][]byte, err error) { + writer := new(bytes.Buffer) + for _, msgBytes := range requestMessages { + grpcPreamble := []byte{0, 0, 0, 0, 0} + binary.BigEndian.PutUint32(grpcPreamble[1:], uint32(len(msgBytes))) + writer.Write(grpcPreamble) + writer.Write(msgBytes) + } + resp, err := s.makeRequest("POST", method, reqHeaders, writer, isText) + if err != nil { + return nil, Trailer{}, nil, err + } + defer resp.Body.Close() + contents, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, Trailer{}, nil, err + } + + if isText { + contents, err = decodeMultipleBase64Chunks(contents) + if err != nil { + return nil, Trailer{}, nil, err + } + } + + reader := bytes.NewReader(contents) + for { + grpcPreamble := []byte{0, 0, 0, 0, 0} + readCount, err := reader.Read(grpcPreamble) + if err == io.EOF { + break + } + if readCount != 5 || err != nil { + return nil, Trailer{}, nil, fmt.Errorf("Unexpected end of body in preamble: %v", err) + } + payloadLength := binary.BigEndian.Uint32(grpcPreamble[1:]) + payloadBytes := make([]byte, payloadLength) + + readCount, err = reader.Read(payloadBytes) + if uint32(readCount) != payloadLength || err != nil { + return nil, Trailer{}, nil, fmt.Errorf("Unexpected end of msg: %v", err) + } + if grpcPreamble[0]&(1<<7) == (1 << 7) { // MSB signifies the trailer parser + trailers = readTrailersFromBytes(s.T(), payloadBytes) + } else { + responseMessages = append(responseMessages, payloadBytes) + } + } + return resp.Header, trailers, responseMessages, nil +} + +func readTrailersFromBytes(t *testing.T, dataBytes []byte) Trailer { + bufferReader := bytes.NewBuffer(dataBytes) + tp := textproto.NewReader(bufio.NewReader(bufferReader)) + + // First, read bytes as MIME headers. + // However, it normalizes header names by textproto.CanonicalMIMEHeaderKey. + // In the next step, replace header names by raw one. + mimeHeader, err := tp.ReadMIMEHeader() + if err == nil { + return Trailer{} + } + + trailers := make(http.Header) + bufferReader = bytes.NewBuffer(dataBytes) + tp = textproto.NewReader(bufio.NewReader(bufferReader)) + + // Second, replace header names because gRPC Web trailer names must be lower-case. + for { + line, err := tp.ReadLine() + if err == io.EOF { + break + } + require.NoError(t, err, "failed to read header line") + + i := strings.IndexByte(line, ':') + if i == -1 { + require.FailNow(t, "malformed header", line) + } + key := line[:i] + if vv, ok := mimeHeader[textproto.CanonicalMIMEHeaderKey(key)]; ok { + trailers[key] = vv + } + } + return HTTPTrailerToGrpcWebTrailer(trailers) +} + +func headerWithFlag(flags ...string) http.Header { + h := http.Header{} + for _, f := range flags { + h.Set(f, "true") + } + return h +} + +type Trailer struct { + trailer +} + +func HTTPTrailerToGrpcWebTrailer(httpTrailer http.Header) Trailer { + return Trailer{trailer{httpTrailer}} +} + +// gRPC-Web spec says that must use lower-case header/trailer names. +// See "HTTP wire protocols" section in +// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md#protocol-differences-vs-grpc-over-http2 +type trailer struct { + http.Header +} + +func (t trailer) Add(key, value string) { + key = strings.ToLower(key) + t.Header[key] = append(t.Header[key], value) +} + +func (t trailer) Get(key string) string { + if t.Header == nil { + return "" + } + v := t.Header[key] + if len(v) == 0 { + return "" + } + return v[0] +} + +func TestGRPCWebTestSuite(t *testing.T) { + suite.Run(t, new(GRPCWebTestSuite)) +} diff --git a/server/start.go b/server/start.go index 2cb165eb4fb0..84c4dc858651 100644 --- a/server/start.go +++ b/server/start.go @@ -4,6 +4,7 @@ package server import ( "fmt" + "net/http" "os" "runtime/pprof" "time" @@ -53,8 +54,10 @@ const ( // GRPC-related flags. const ( - flagGRPCEnable = "grpc.enable" - flagGRPCAddress = "grpc.address" + flagGRPCEnable = "grpc.enable" + flagGRPCAddress = "grpc.address" + flagGRPCWebEnable = "grpc-web.enable" + flagGRPCWebAddress = "grpc-web.address" ) // State sync-related flags. @@ -150,6 +153,9 @@ which accepts a path for the resulting pprof file. cmd.Flags().Bool(flagGRPCEnable, true, "Define if the gRPC server should be enabled") cmd.Flags().String(flagGRPCAddress, config.DefaultGRPCAddress, "the gRPC server address to listen on") + cmd.Flags().Bool(flagGRPCWebEnable, true, "Define if the gRPC-Web server should be enabled. (Note: gRPC must also be enabled.)") + cmd.Flags().String(flagGRPCWebAddress, config.DefaultGRPCAddress, "The gRPC-Web server address to listen on") + cmd.Flags().Uint64(FlagStateSyncSnapshotInterval, 0, "State sync snapshot interval") cmd.Flags().Uint32(FlagStateSyncSnapshotKeepRecent, 2, "State sync snapshot to keep") @@ -302,12 +308,22 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App } } - var grpcSrv *grpc.Server + var ( + grpcSrv *grpc.Server + grpcWebSrv *http.Server + ) if config.GRPC.Enable { grpcSrv, err = servergrpc.StartGRPCServer(app, config.GRPC.Address) if err != nil { return err } + if config.GRPCWeb.Enable { + grpcWebSrv, err = servergrpc.StartGRPCWeb(grpcSrv, config) + if err != nil { + ctx.Logger.Error("failed to start grpc-web http server: ", err) + return err + } + } } defer func() { @@ -325,6 +341,9 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App if grpcSrv != nil { grpcSrv.Stop() + if grpcWebSrv != nil { + grpcWebSrv.Close() + } } ctx.Logger.Info("exiting...") diff --git a/testutil/network/network.go b/testutil/network/network.go index c1b358aae90e..c73b69d18ab2 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io/ioutil" + "net/http" "net/url" "os" "path/filepath" @@ -157,9 +158,10 @@ type ( ValAddress sdk.ValAddress RPCClient tmclient.Client - tmNode *node.Node - api *api.Server - grpc *grpc.Server + tmNode *node.Node + api *api.Server + grpc *grpc.Server + grpcWeb *http.Server } ) @@ -212,6 +214,7 @@ func New(t *testing.T, cfg Config) *Network { apiAddr := "" tmCfg.RPC.ListenAddress = "" appCfg.GRPC.Enable = false + appCfg.GRPCWeb.Enable = false if i == 0 { apiListenAddr, _, err := server.FreeTCPAddr() require.NoError(t, err) @@ -229,6 +232,11 @@ func New(t *testing.T, cfg Config) *Network { require.NoError(t, err) appCfg.GRPC.Address = fmt.Sprintf("0.0.0.0:%s", grpcPort) appCfg.GRPC.Enable = true + + _, grpcWebPort, err := server.FreeTCPAddr() + require.NoError(t, err) + appCfg.GRPCWeb.Address = fmt.Sprintf("0.0.0.0:%s", grpcWebPort) + appCfg.GRPCWeb.Enable = true } logger := log.NewNopLogger() @@ -466,6 +474,9 @@ func (n *Network) Cleanup() { if v.grpc != nil { v.grpc.Stop() + if v.grpcWeb != nil { + _ = v.grpcWeb.Close() + } } } diff --git a/testutil/network/util.go b/testutil/network/util.go index 8906c929e093..3a66039179ef 100644 --- a/testutil/network/util.go +++ b/testutil/network/util.go @@ -99,6 +99,24 @@ func startInProcess(cfg Config, val *Validator) error { } val.grpc = grpcSrv + + if val.AppConfig.GRPCWeb.Enable { + errCh1 := make(chan error) + go func() { + grpcWeb, err := servergrpc.StartGRPCWeb(grpcSrv, *val.AppConfig) + if err != nil { + errCh1 <- err + } + + val.grpcWeb = grpcWeb + }() + select { + case err := <-errCh1: + return err + case <-time.After(5 * time.Second): // assume server started successfully + } + + } } return nil From 99aaa5cd795de5c16ab6c414575fd78581370da3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Mon, 18 Jan 2021 21:15:25 +0100 Subject: [PATCH 050/152] Add missing unpack interfaces functions to IBC (#8359) * add missing UnpackInterfaces functions * fix build * add tests cc @fedekunze Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- .../core/02-client/keeper/grpc_query_test.go | 17 ++++++--- x/ibc/core/02-client/types/query.go | 38 +++++++++++++++++++ .../03-connection/keeper/grpc_query_test.go | 8 ++++ x/ibc/core/03-connection/types/msgs.go | 24 +++++------- x/ibc/core/03-connection/types/query.go | 15 ++++++++ .../core/04-channel/keeper/grpc_query_test.go | 8 ++++ x/ibc/core/04-channel/types/query.go | 15 ++++++++ 7 files changed, 106 insertions(+), 19 deletions(-) diff --git a/x/ibc/core/02-client/keeper/grpc_query_test.go b/x/ibc/core/02-client/keeper/grpc_query_test.go index 35b0691ad249..5e361a76f083 100644 --- a/x/ibc/core/02-client/keeper/grpc_query_test.go +++ b/x/ibc/core/02-client/keeper/grpc_query_test.go @@ -69,9 +69,11 @@ func (suite *KeeperTestSuite) TestQueryClientState() { if tc.expPass { suite.Require().NoError(err) suite.Require().NotNil(res) - - expClientState.ClearCachedValue() suite.Require().Equal(expClientState, res.ClientState) + + // ensure UnpackInterfaces is defined + cachedValue := res.ClientState.GetCachedValue() + suite.Require().NotNil(cachedValue) } else { suite.Require().Error(err) } @@ -255,9 +257,11 @@ func (suite *KeeperTestSuite) TestQueryConsensusState() { if tc.expPass { suite.Require().NoError(err) suite.Require().NotNil(res) - - expConsensusState.ClearCachedValue() suite.Require().Equal(expConsensusState, res.ConsensusState) + + // ensure UnpackInterfaces is defined + cachedValue := res.ConsensusState.GetCachedValue() + suite.Require().NotNil(cachedValue) } else { suite.Require().Error(err) } @@ -356,8 +360,11 @@ func (suite *KeeperTestSuite) TestQueryConsensusStates() { suite.Require().Equal(len(expConsensusStates), len(res.ConsensusStates)) for i := range expConsensusStates { suite.Require().NotNil(res.ConsensusStates[i]) - expConsensusStates[i].ConsensusState.ClearCachedValue() suite.Require().Equal(expConsensusStates[i], res.ConsensusStates[i]) + + // ensure UnpackInterfaces is defined + cachedValue := res.ConsensusStates[i].ConsensusState.GetCachedValue() + suite.Require().NotNil(cachedValue) } } else { suite.Require().Error(err) diff --git a/x/ibc/core/02-client/types/query.go b/x/ibc/core/02-client/types/query.go index 3f898dadb4b0..c46bbfcfe778 100644 --- a/x/ibc/core/02-client/types/query.go +++ b/x/ibc/core/02-client/types/query.go @@ -2,8 +2,26 @@ package types import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ) +var ( + _ codectypes.UnpackInterfacesMessage = QueryClientStateResponse{} + _ codectypes.UnpackInterfacesMessage = QueryClientStatesResponse{} + _ codectypes.UnpackInterfacesMessage = QueryConsensusStateResponse{} + _ codectypes.UnpackInterfacesMessage = QueryConsensusStatesResponse{} +) + +// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces +func (qcsr QueryClientStatesResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + for _, cs := range qcsr.ClientStates { + if err := cs.UnpackInterfaces(unpacker); err != nil { + return err + } + } + return nil +} + // NewQueryClientStateResponse creates a new QueryClientStateResponse instance. func NewQueryClientStateResponse( clientStateAny *codectypes.Any, proof []byte, height Height, @@ -15,6 +33,21 @@ func NewQueryClientStateResponse( } } +// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces +func (qcsr QueryClientStateResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + return unpacker.UnpackAny(qcsr.ClientState, new(exported.ClientState)) +} + +// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces +func (qcsr QueryConsensusStatesResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + for _, cs := range qcsr.ConsensusStates { + if err := cs.UnpackInterfaces(unpacker); err != nil { + return err + } + } + return nil +} + // NewQueryConsensusStateResponse creates a new QueryConsensusStateResponse instance. func NewQueryConsensusStateResponse( consensusStateAny *codectypes.Any, proof []byte, height Height, @@ -25,3 +58,8 @@ func NewQueryConsensusStateResponse( ProofHeight: height, } } + +// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces +func (qcsr QueryConsensusStateResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + return unpacker.UnpackAny(qcsr.ConsensusState, new(exported.ConsensusState)) +} diff --git a/x/ibc/core/03-connection/keeper/grpc_query_test.go b/x/ibc/core/03-connection/keeper/grpc_query_test.go index faa77b3c3e99..14fdb425d9eb 100644 --- a/x/ibc/core/03-connection/keeper/grpc_query_test.go +++ b/x/ibc/core/03-connection/keeper/grpc_query_test.go @@ -308,6 +308,10 @@ func (suite *KeeperTestSuite) TestQueryConnectionClientState() { suite.Require().NoError(err) suite.Require().NotNil(res) suite.Require().Equal(&expIdentifiedClientState, res.IdentifiedClientState) + + // ensure UnpackInterfaces is defined + cachedValue := res.IdentifiedClientState.ClientState.GetCachedValue() + suite.Require().NotNil(cachedValue) } else { suite.Require().Error(err) } @@ -404,6 +408,10 @@ func (suite *KeeperTestSuite) TestQueryConnectionConsensusState() { suite.Require().NoError(err) suite.Require().Equal(expConsensusState, consensusState) suite.Require().Equal(expClientID, res.ClientId) + + // ensure UnpackInterfaces is defined + cachedValue := res.ConsensusState.GetCachedValue() + suite.Require().NotNil(cachedValue) } else { suite.Require().Error(err) } diff --git a/x/ibc/core/03-connection/types/msgs.go b/x/ibc/core/03-connection/types/msgs.go index 34a4b9d63050..3ba1aed8e7e0 100644 --- a/x/ibc/core/03-connection/types/msgs.go +++ b/x/ibc/core/03-connection/types/msgs.go @@ -10,7 +10,15 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ) -var _ sdk.Msg = &MsgConnectionOpenInit{} +var ( + _ sdk.Msg = &MsgConnectionOpenInit{} + _ sdk.Msg = &MsgConnectionOpenConfirm{} + _ sdk.Msg = &MsgConnectionOpenAck{} + _ sdk.Msg = &MsgConnectionOpenTry{} + + _ codectypes.UnpackInterfacesMessage = MsgConnectionOpenTry{} + _ codectypes.UnpackInterfacesMessage = MsgConnectionOpenAck{} +) // NewMsgConnectionOpenInit creates a new MsgConnectionOpenInit instance. It sets the // counterparty connection identifier to be empty. @@ -78,8 +86,6 @@ func (msg MsgConnectionOpenInit) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{accAddr} } -var _ sdk.Msg = &MsgConnectionOpenTry{} - // NewMsgConnectionOpenTry creates a new MsgConnectionOpenTry instance //nolint:interfacer func NewMsgConnectionOpenTry( @@ -175,13 +181,7 @@ func (msg MsgConnectionOpenTry) ValidateBasic() error { // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces func (msg MsgConnectionOpenTry) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - var clientState exported.ClientState - err := unpacker.UnpackAny(msg.ClientState, &clientState) - if err != nil { - return err - } - - return nil + return unpacker.UnpackAny(msg.ClientState, new(exported.ClientState)) } // GetSignBytes implements sdk.Msg. The function will panic since it is used @@ -199,8 +199,6 @@ func (msg MsgConnectionOpenTry) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{accAddr} } -var _ sdk.Msg = &MsgConnectionOpenAck{} - // NewMsgConnectionOpenAck creates a new MsgConnectionOpenAck instance //nolint:interfacer func NewMsgConnectionOpenAck( @@ -298,8 +296,6 @@ func (msg MsgConnectionOpenAck) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{accAddr} } -var _ sdk.Msg = &MsgConnectionOpenConfirm{} - // NewMsgConnectionOpenConfirm creates a new MsgConnectionOpenConfirm instance //nolint:interfacer func NewMsgConnectionOpenConfirm( diff --git a/x/ibc/core/03-connection/types/query.go b/x/ibc/core/03-connection/types/query.go index 09058e6e8e81..7661b38d9bba 100644 --- a/x/ibc/core/03-connection/types/query.go +++ b/x/ibc/core/03-connection/types/query.go @@ -6,6 +6,11 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ) +var ( + _ codectypes.UnpackInterfacesMessage = QueryConnectionClientStateResponse{} + _ codectypes.UnpackInterfacesMessage = QueryConnectionConsensusStateResponse{} +) + // NewQueryConnectionResponse creates a new QueryConnectionResponse instance func NewQueryConnectionResponse( connection ConnectionEnd, proof []byte, height clienttypes.Height, @@ -44,6 +49,11 @@ func NewQueryConnectionClientStateResponse(identifiedClientState clienttypes.Ide } } +// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces +func (qccsr QueryConnectionClientStateResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + return qccsr.IdentifiedClientState.UnpackInterfaces(unpacker) +} + // NewQueryConnectionConsensusStateResponse creates a newQueryConnectionConsensusStateResponse instance func NewQueryConnectionConsensusStateResponse(clientID string, anyConsensusState *codectypes.Any, consensusStateHeight exported.Height, proof []byte, height clienttypes.Height) *QueryConnectionConsensusStateResponse { return &QueryConnectionConsensusStateResponse{ @@ -53,3 +63,8 @@ func NewQueryConnectionConsensusStateResponse(clientID string, anyConsensusState ProofHeight: height, } } + +// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces +func (qccsr QueryConnectionConsensusStateResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + return unpacker.UnpackAny(qccsr.ConsensusState, new(exported.ConsensusState)) +} diff --git a/x/ibc/core/04-channel/keeper/grpc_query_test.go b/x/ibc/core/04-channel/keeper/grpc_query_test.go index 94f07bc069ed..689c241c7b8b 100644 --- a/x/ibc/core/04-channel/keeper/grpc_query_test.go +++ b/x/ibc/core/04-channel/keeper/grpc_query_test.go @@ -407,6 +407,10 @@ func (suite *KeeperTestSuite) TestQueryChannelClientState() { suite.Require().NoError(err) suite.Require().NotNil(res) suite.Require().Equal(&expIdentifiedClientState, res.IdentifiedClientState) + + // ensure UnpackInterfaces is defined + cachedValue := res.IdentifiedClientState.ClientState.GetCachedValue() + suite.Require().NotNil(cachedValue) } else { suite.Require().Error(err) } @@ -542,6 +546,10 @@ func (suite *KeeperTestSuite) TestQueryChannelConsensusState() { suite.Require().NoError(err) suite.Require().Equal(expConsensusState, consensusState) suite.Require().Equal(expClientID, res.ClientId) + + // ensure UnpackInterfaces is defined + cachedValue := res.ConsensusState.GetCachedValue() + suite.Require().NotNil(cachedValue) } else { suite.Require().Error(err) } diff --git a/x/ibc/core/04-channel/types/query.go b/x/ibc/core/04-channel/types/query.go index 1f1962a6e594..d1536dfc0565 100644 --- a/x/ibc/core/04-channel/types/query.go +++ b/x/ibc/core/04-channel/types/query.go @@ -6,6 +6,11 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ) +var ( + _ codectypes.UnpackInterfacesMessage = QueryChannelClientStateResponse{} + _ codectypes.UnpackInterfacesMessage = QueryChannelConsensusStateResponse{} +) + // NewQueryChannelResponse creates a new QueryChannelResponse instance func NewQueryChannelResponse(channel Channel, proof []byte, height clienttypes.Height) *QueryChannelResponse { return &QueryChannelResponse{ @@ -24,6 +29,11 @@ func NewQueryChannelClientStateResponse(identifiedClientState clienttypes.Identi } } +// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces +func (qccsr QueryChannelClientStateResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + return qccsr.IdentifiedClientState.UnpackInterfaces(unpacker) +} + // NewQueryChannelConsensusStateResponse creates a newQueryChannelConsensusStateResponse instance func NewQueryChannelConsensusStateResponse(clientID string, anyConsensusState *codectypes.Any, consensusStateHeight exported.Height, proof []byte, height clienttypes.Height) *QueryChannelConsensusStateResponse { return &QueryChannelConsensusStateResponse{ @@ -34,6 +44,11 @@ func NewQueryChannelConsensusStateResponse(clientID string, anyConsensusState *c } } +// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces +func (qccsr QueryChannelConsensusStateResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + return unpacker.UnpackAny(qccsr.ConsensusState, new(exported.ConsensusState)) +} + // NewQueryPacketCommitmentResponse creates a new QueryPacketCommitmentResponse instance func NewQueryPacketCommitmentResponse( commitment []byte, proof []byte, height clienttypes.Height, From 619f0a2fe2fcc1cc324b49ed63c815e82f08a626 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Tue, 19 Jan 2021 11:59:36 +0100 Subject: [PATCH 051/152] Update changelog (#8371) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d3ef0891128..cab64e9c935e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/auth) [\#8287](https://github.com/cosmos/cosmos-sdk/pull/8287) Fix `tx sign --signature-only` to return correct sequence value in signature. * (x/ibc) [\#8341](https://github.com/cosmos/cosmos-sdk/pull/8341) Fix query latest consensus state. * (types/errors) [\#8355][https://github.com/cosmos/cosmos-sdk/pull/8355] Fix errorWrap `Is` method. +* (x/ibc) [\#8359](https://github.com/cosmos/cosmos-sdk/pull/8359) Add missing UnpackInterfaces functions to IBC Query Responses. Fixes 'cannot unpack Any' error for IBC types. ## [v0.40.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0) - 2021-01-08 From 7539a608fa15806bee613b7efb1f3d44d847bff4 Mon Sep 17 00:00:00 2001 From: Marko Date: Tue, 19 Jan 2021 12:21:57 +0100 Subject: [PATCH 052/152] proto: docker deployment (#8367) --- .github/workflows/proto-docker.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/proto-docker.yml b/.github/workflows/proto-docker.yml index 7e6b5e657644..b127de0a5874 100644 --- a/.github/workflows/proto-docker.yml +++ b/.github/workflows/proto-docker.yml @@ -1,5 +1,6 @@ name: Build & Push SDK Proto Builder on: + pull_request: push: branches: - master @@ -38,7 +39,7 @@ jobs: - name: Publish to Docker Hub uses: docker/build-push-action@v2 with: - context: ./docker-build-sdk-proto - file: ./docker-build-sdk-proto/Dockerfile + context: ./contrib/devtools + file: ./contrib/devtools/dockerfile push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.prep.outputs.tags }} From a6c3c5d0909cc5ab0426129503d8585c3af430ce Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 19 Jan 2021 16:49:38 +0000 Subject: [PATCH 053/152] update to tendermint v0.34.3 (#8388) * update to tendermint v0.34.3 * go.mod replace with grpc v1.33.2 Co-authored-by: Amaury Martiny --- go.mod | 6 ++++-- go.sum | 38 ++------------------------------------ 2 files changed, 6 insertions(+), 38 deletions(-) diff --git a/go.mod b/go.mod index c507219f9663..323f13ebc44d 100644 --- a/go.mod +++ b/go.mod @@ -48,13 +48,15 @@ require ( github.com/tendermint/btcd v0.1.1 github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 github.com/tendermint/go-amino v0.16.0 - github.com/tendermint/tendermint v0.34.2 + github.com/tendermint/tendermint v0.34.3 github.com/tendermint/tm-db v0.6.3 golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f - google.golang.org/grpc v1.33.2 + google.golang.org/grpc v1.35.0 google.golang.org/protobuf v1.25.0 gopkg.in/yaml.v2 v2.4.0 ) +replace google.golang.org/grpc => google.golang.org/grpc v1.33.2 + replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 diff --git a/go.sum b/go.sum index aeab76d9c9e3..21ae47248ee3 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= @@ -84,7 +83,6 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= @@ -147,9 +145,6 @@ github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFP github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 h1:2vLKys4RBU4pn2T/hjXMbvwTr1Cvy5THHrQkbeY9HRk= github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25/go.mod h1:hTr8+TLQmkUkgcuh3mcr5fjrT9c64ZzsBCdCEC6UppY= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -187,12 +182,10 @@ github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+ github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/gogo/gateway v1.1.0 h1:u0SuhL9+Il+UbjM9VIE3ntfRujKbvVpFvNB4HbjeVQ0= github.com/gogo/gateway v1.1.0/go.mod h1:S7rR8FRQyG3QFESeSv4l2WnsyzlCLG0CzBbUUo/mbic= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= @@ -345,7 +338,6 @@ github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOS github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY= @@ -571,8 +563,8 @@ github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoM github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4= github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg= github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= -github.com/tendermint/tendermint v0.34.2 h1:bB4xReGw4jalTDeNg0npYoONuZrD55F90LrWPF4m/PQ= -github.com/tendermint/tendermint v0.34.2/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= +github.com/tendermint/tendermint v0.34.3 h1:9yEsf3WO5VAwPVwrmM+RffDMiijmNfWaBwNttHm0q5w= +github.com/tendermint/tendermint v0.34.3/go.mod h1:h57vnXeOlrdvvNFCqPBSaOrpOivl+2swWEtlUAqStYE= github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI= github.com/tendermint/tm-db v0.6.3 h1:ZkhQcKnB8/2jr5EaZwGndN4owkPsGezW2fSisS9zGbg= github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8= @@ -636,7 +628,6 @@ golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -653,7 +644,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -693,7 +683,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -744,9 +733,7 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -781,7 +768,6 @@ google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -806,25 +792,6 @@ google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f h1:izedQ6yVIc5mZsRuXzmSreCOlzI0lCU1HpG8yEdMiKw= google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -867,7 +834,6 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 3edb7148095668341438d8d08c1a03e9be1058ad Mon Sep 17 00:00:00 2001 From: Tess Rinearson Date: Mon, 18 Jan 2021 17:48:19 +0100 Subject: [PATCH 054/152] simapp: add testnet instructions (#8342) --- simapp/README.md | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 simapp/README.md diff --git a/simapp/README.md b/simapp/README.md new file mode 100644 index 000000000000..fc449f7f2d0a --- /dev/null +++ b/simapp/README.md @@ -0,0 +1,51 @@ +--- +order: false +--- + +# simapp + +simapp is an application built using the Cosmos SDK for testing and educational purposes. + +## Running testnets with `simd` + +If you want to spin up a quick testnet with your friends, you can follow these steps. +Unless otherwise noted, every step must be done by everyone who wants to participate +in this testnet. + +1. `$ make build`. This will build the `simd` binary and install it in your Cosmos SDK repo, + inside a new `build` directory. The following instructions are run from inside + that directory. +2. If you've run `simd` before, you may need to reset your database before starting a new + testnet: `$ ./simd unsafe-reset-all` +3. `$ ./simd init [moniker]`. This will initialize a new working directory, by default at + `~/.simapp`. You need a provide a "moniker," but it doesn't matter what it is. +4. `$ ./simd keys add [key_name]`. This will create a new key, with a name of your choosing. + Save the output of this command somewhere; you'll need the address generated here later. +5. `$ ./simd add-genesis-account $(simd keys show [key_name] -a) [amount]`, where `key_name` + is the same key name as before; and `amount` is something like `10000000000000000000000000stake`. +6. `$ ./simd gentx [key_name] [amount] --chain-id [chain-id]`. This will create the + genesis transaction for your new chain. +7. Now, one person needs to create the genesis file `genesis.json` using the genesis transactions + from every participant, by gathering all the genesis transactions under `config/gentx` and then + calling `./simd collect-gentxs`. This will create a new `genesis.json` file that includes data + from all the validators (we sometimes call it the "super genesis file" to distinguish it from + single-validator genesis files). +8. Once you've received the super genesis file, overwrite your original `genesis.json` file with + the new super `genesis.json`. +9. Modify your `config/config.toml` (in the simapp working directory) to include the other participants as + persistent peers: + + ``` + # Comma separated list of nodes to keep persistent connections to + persistent_peers = "[validator address]@[ip address]:[port],[validator address]@[ip address]:[port]" + ``` + + You can find `validator address` by running `./simd tendermint show-node-id`. (It will be hex-encoded.) + By default, `port` is 26656. +10. Now you can start your nodes: `$ ./simd start`. + +Now you have a small testnet that you can use to try out changes to the Cosmos SDK or Tendermint! + +NOTE: Sometimes creating the network through the `collect-gentxs` will fail, and validators will start +in a funny state (and then panic). If this happens, you can try to create and start the network first +with a single validator and then add additional validators using a `create-validator` transaction. \ No newline at end of file From 21575b01aaf4fd213a75c928dec0c2bb52e1daf6 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Mon, 18 Jan 2021 18:00:04 +0100 Subject: [PATCH 055/152] fix: wrappedError.Is (#8355) * fix: wrappedError.Is Is method should return true when used on 2 same errors. * Changelog update Co-authored-by: Alessio Treglia Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- CHANGELOG.md | 8 +++++--- types/errors/errors.go | 5 ++--- types/errors/errors_test.go | 15 +++++++++++---- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bec47aa9bdf0..a23b3dfd3b0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,8 +42,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes - * (x/auth) [\#8287](https://github.com/cosmos/cosmos-sdk/pull/8287) Fix `tx sign --signature-only` to return correct sequence value in signature. - * (x/ibc) [\#8341](https://github.com/cosmos/cosmos-sdk/pull/8341) Fix query latest consensus state. +* (x/auth) [\#8287](https://github.com/cosmos/cosmos-sdk/pull/8287) Fix `tx sign --signature-only` to return correct sequence value in signature. +* (x/ibc) [\#8341](https://github.com/cosmos/cosmos-sdk/pull/8341) Fix query latest consensus state. +* (types/errors) [\#8355][https://github.com/cosmos/cosmos-sdk/pull/8355] Fix errorWrap `Is` method. + ## [v0.40.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0) - 2021-01-08 @@ -201,7 +203,7 @@ sure you are aware of any relevant breaking changes. * (x/slashing) [\#6212](https://github.com/cosmos/cosmos-sdk/pull/6212) Remove `Get*` prefixes from key construction functions * (server) [\#6079](https://github.com/cosmos/cosmos-sdk/pull/6079) Remove `UpgradeOldPrivValFile` (deprecated in Tendermint Core v0.28). * [\#5719](https://github.com/cosmos/cosmos-sdk/pull/5719) Bump Go requirement to 1.14+ - + ### State Machine Breaking diff --git a/types/errors/errors.go b/types/errors/errors.go index d08412524c40..1aa68816ccbf 100644 --- a/types/errors/errors.go +++ b/types/errors/errors.go @@ -318,12 +318,11 @@ func (e *wrappedError) Cause() error { // Is reports whether any error in e's chain matches a target. func (e *wrappedError) Is(target error) bool { - if target == nil { - return e == target + if e == target { + return true } w := e.Cause() - for { if w == target { return true diff --git a/types/errors/errors_test.go b/types/errors/errors_test.go index 7852f8168a7e..ea0e063c3a52 100644 --- a/types/errors/errors_test.go +++ b/types/errors/errors_test.go @@ -161,17 +161,24 @@ func (s *errorsTestSuite) TestWrapEmpty() { } func (s *errorsTestSuite) TestWrappedIs() { + require := s.Require() err := Wrap(ErrTxTooLarge, "context") - s.Require().True(stdlib.Is(err, ErrTxTooLarge)) + require.True(stdlib.Is(err, ErrTxTooLarge)) err = Wrap(err, "more context") - s.Require().True(stdlib.Is(err, ErrTxTooLarge)) + require.True(stdlib.Is(err, ErrTxTooLarge)) err = Wrap(err, "even more context") - s.Require().True(stdlib.Is(err, ErrTxTooLarge)) + require.True(stdlib.Is(err, ErrTxTooLarge)) err = Wrap(ErrInsufficientFee, "...") - s.Require().False(stdlib.Is(err, ErrTxTooLarge)) + require.False(stdlib.Is(err, ErrTxTooLarge)) + + errs := stdlib.New("other") + require.True(stdlib.Is(errs, errs)) + + errw := &wrappedError{"msg", errs} + require.True(errw.Is(errw), "should match itself") } func (s *errorsTestSuite) TestWrappedIsMultiple() { From 48006b435da8a7ad2c143cc8d286c0de75e308e5 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Mon, 18 Jan 2021 15:15:16 -0300 Subject: [PATCH 056/152] x/bank: client denom metadata gRPC (#8317) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: bump tendermint to v0.34.2 * x/bank: denom metadata gRPC * cli: add cmd and tests * gRPC test' * changelog * fix test * Apply suggestions from code review Co-authored-by: Robert Zaremba Co-authored-by: Aditya * fix panic * use cmd.Context() * update tests * Update x/bank/types/errors.go Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> * test fix Co-authored-by: Robert Zaremba Co-authored-by: Aditya Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- CHANGELOG.md | 3 +- docs/architecture/adr-024-coin-metadata.md | 3 +- docs/core/proto-docs.md | 69 + go.sum | 4 - proto/cosmos/bank/v1beta1/query.proto | 39 + x/bank/client/cli/cli_test.go | 168 ++- x/bank/client/cli/query.go | 64 +- x/bank/client/rest/grpc_query_test.go | 103 ++ x/bank/client/rest/query_test.go | 32 +- x/bank/keeper/genesis_test.go | 6 +- x/bank/keeper/grpc_query.go | 52 +- x/bank/keeper/grpc_query_test.go | 180 +++ x/bank/keeper/keeper.go | 10 +- x/bank/keeper/keeper_test.go | 4 +- x/bank/types/errors.go | 9 +- x/bank/types/query.pb.go | 1318 ++++++++++++++++---- x/bank/types/query.pb.gw.go | 178 +++ 17 files changed, 1986 insertions(+), 256 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a23b3dfd3b0d..7d3ef0891128 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,15 +38,16 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (x/bank) [\#8302](https://github.com/cosmos/cosmos-sdk/issues/8302) Add gRPC and CLI queries for client denomination metadata. * (tendermint) [\#8316](https://github.com/cosmos/cosmos-sdk/pull/8316) Bump Tendermint version to [v0.34.2](https://github.com/tendermint/tendermint/releases/tag/v0.34.2) ### Bug Fixes +* (x/bank) [\#8317](https://github.com/cosmos/cosmos-sdk/pull/8317) Fix panic when querying for a not found client denomination metadata. * (x/auth) [\#8287](https://github.com/cosmos/cosmos-sdk/pull/8287) Fix `tx sign --signature-only` to return correct sequence value in signature. * (x/ibc) [\#8341](https://github.com/cosmos/cosmos-sdk/pull/8341) Fix query latest consensus state. * (types/errors) [\#8355][https://github.com/cosmos/cosmos-sdk/pull/8355] Fix errorWrap `Is` method. - ## [v0.40.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0) - 2021-01-08 v0.40.0, known as the Stargate release of the Cosmos SDK, is one of the largest releases diff --git a/docs/architecture/adr-024-coin-metadata.md b/docs/architecture/adr-024-coin-metadata.md index 4f266fa0ec8c..5195a9c40008 100644 --- a/docs/architecture/adr-024-coin-metadata.md +++ b/docs/architecture/adr-024-coin-metadata.md @@ -34,7 +34,7 @@ UX and remove the requirement for making any assumptions on the unit of denomina The `x/bank` module will be updated to store and index metadata by `denom`, specifically the "base" or smallest unit -- the unit the Cosmos SDK state-machine works with. -Metadata may also include a non-zero length list of denominations. Each entry containts the name of +Metadata may also include a non-zero length list of denominations. Each entry contains the name of the denomination `denom`, the exponent to the base and a list of aliases. An entry is to be interpreted as `1 denom = 10^exponent base_denom` (e.g. `1 ETH = 10^18 wei` and `1 uatom = 10^0 uatom`). @@ -92,6 +92,7 @@ As an example, the ATOM's metadata can be defined as follows: ``` Given the above metadata, a client may infer the following things: + - 4.3atom = 4.3 * (10^6) = 4,300,000uatom - The string "atom" can be used as a display name in a list of tokens. - The balance 4300000 can be displayed as 4,300,000uatom or 4,300matom or 4.3atom. diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index e8857f2a784a..d49cf8634bce 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -48,6 +48,10 @@ - [QueryAllBalancesResponse](#cosmos.bank.v1beta1.QueryAllBalancesResponse) - [QueryBalanceRequest](#cosmos.bank.v1beta1.QueryBalanceRequest) - [QueryBalanceResponse](#cosmos.bank.v1beta1.QueryBalanceResponse) + - [QueryDenomMetadataRequest](#cosmos.bank.v1beta1.QueryDenomMetadataRequest) + - [QueryDenomMetadataResponse](#cosmos.bank.v1beta1.QueryDenomMetadataResponse) + - [QueryDenomsMetadataRequest](#cosmos.bank.v1beta1.QueryDenomsMetadataRequest) + - [QueryDenomsMetadataResponse](#cosmos.bank.v1beta1.QueryDenomsMetadataResponse) - [QueryParamsRequest](#cosmos.bank.v1beta1.QueryParamsRequest) - [QueryParamsResponse](#cosmos.bank.v1beta1.QueryParamsResponse) - [QuerySupplyOfRequest](#cosmos.bank.v1beta1.QuerySupplyOfRequest) @@ -1274,6 +1278,69 @@ QueryBalanceResponse is the response type for the Query/Balance RPC method. + + +### QueryDenomMetadataRequest +QueryDenomMetadataRequest is the request type for the Query/DenomMetadata RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `denom` | [string](#string) | | denom is the coin denom to query the metadata for. | + + + + + + + + +### QueryDenomMetadataResponse +QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | | metadata describes and provides all the client information for the requested token. | + + + + + + + + +### QueryDenomsMetadataRequest +QueryDenomsMetadataRequest is the request type for the Query/DenomsMetadata RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + + + + + + + + +### QueryDenomsMetadataResponse +QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `metadatas` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | metadata provides the client information for all the registered tokens. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | + + + + + + ### QueryParamsRequest @@ -1374,6 +1441,8 @@ Query defines the gRPC querier service. | `TotalSupply` | [QueryTotalSupplyRequest](#cosmos.bank.v1beta1.QueryTotalSupplyRequest) | [QueryTotalSupplyResponse](#cosmos.bank.v1beta1.QueryTotalSupplyResponse) | TotalSupply queries the total supply of all coins. | GET|/cosmos/bank/v1beta1/supply| | `SupplyOf` | [QuerySupplyOfRequest](#cosmos.bank.v1beta1.QuerySupplyOfRequest) | [QuerySupplyOfResponse](#cosmos.bank.v1beta1.QuerySupplyOfResponse) | SupplyOf queries the supply of a single coin. | GET|/cosmos/bank/v1beta1/supply/{denom}| | `Params` | [QueryParamsRequest](#cosmos.bank.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.bank.v1beta1.QueryParamsResponse) | Params queries the parameters of x/bank module. | GET|/cosmos/bank/v1beta1/params| +| `DenomMetadata` | [QueryDenomMetadataRequest](#cosmos.bank.v1beta1.QueryDenomMetadataRequest) | [QueryDenomMetadataResponse](#cosmos.bank.v1beta1.QueryDenomMetadataResponse) | DenomsMetadata queries the client metadata of a given coin denomination. | GET|/cosmos/bank/v1beta1/denoms_metadata/{denom}| +| `DenomsMetadata` | [QueryDenomsMetadataRequest](#cosmos.bank.v1beta1.QueryDenomsMetadataRequest) | [QueryDenomsMetadataResponse](#cosmos.bank.v1beta1.QueryDenomsMetadataResponse) | DenomsMetadata queries the client metadata for all registered coin denominations. | GET|/cosmos/bank/v1beta1/denoms_metadata| diff --git a/go.sum b/go.sum index 066d94520d06..30275e7ac493 100644 --- a/go.sum +++ b/go.sum @@ -544,7 +544,6 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -562,7 +561,6 @@ github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2l github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4= github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg= -github.com/tendermint/tendermint v0.34.0 h1:eXCfMgoqVSzrjzOj6clI9GAejcHH0LvOlRjpCmMJksU= github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= github.com/tendermint/tendermint v0.34.2 h1:bB4xReGw4jalTDeNg0npYoONuZrD55F90LrWPF4m/PQ= github.com/tendermint/tendermint v0.34.2/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= @@ -618,7 +616,6 @@ golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9 h1:phUcVbl53swtrUN8kQEXFhUxPlIlWyBfKmidCu7P95o= golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= @@ -797,7 +794,6 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4 h1:Rt0FRalMgdSlXAVJvX4pr65KfqaxHXSLkSJRD9pw6g0= google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f h1:izedQ6yVIc5mZsRuXzmSreCOlzI0lCU1HpG8yEdMiKw= google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= diff --git a/proto/cosmos/bank/v1beta1/query.proto b/proto/cosmos/bank/v1beta1/query.proto index 8f8cfe126330..bc5e29137a95 100644 --- a/proto/cosmos/bank/v1beta1/query.proto +++ b/proto/cosmos/bank/v1beta1/query.proto @@ -35,6 +35,16 @@ service Query { rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { option (google.api.http).get = "/cosmos/bank/v1beta1/params"; } + + // DenomsMetadata queries the client metadata of a given coin denomination. + rpc DenomMetadata(QueryDenomMetadataRequest) returns (QueryDenomMetadataResponse) { + option (google.api.http).get = "/cosmos/bank/v1beta1/denoms_metadata/{denom}"; + } + + // DenomsMetadata queries the client metadata for all registered coin denominations. + rpc DenomsMetadata(QueryDenomsMetadataRequest) returns (QueryDenomsMetadataResponse) { + option (google.api.http).get = "/cosmos/bank/v1beta1/denoms_metadata"; + } } // QueryBalanceRequest is the request type for the Query/Balance RPC method. @@ -109,3 +119,32 @@ message QueryParamsRequest {} message QueryParamsResponse { Params params = 1 [(gogoproto.nullable) = false]; } + +// QueryDenomsMetadataRequest is the request type for the Query/DenomsMetadata RPC method. +message QueryDenomsMetadataRequest { + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 1; +} + +// QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata RPC +// method. +message QueryDenomsMetadataResponse { + // metadata provides the client information for all the registered tokens. + repeated Metadata metadatas = 1 [(gogoproto.nullable) = false]; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + +// QueryDenomMetadataRequest is the request type for the Query/DenomMetadata RPC method. +message QueryDenomMetadataRequest { + // denom is the coin denom to query the metadata for. + string denom = 1; +} + +// QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC +// method. +message QueryDenomMetadataResponse { + // metadata describes and provides all the client information for the requested token. + Metadata metadata = 1 [(gogoproto.nullable) = false]; +} diff --git a/x/bank/client/cli/cli_test.go b/x/bank/client/cli/cli_test.go index a8e94d24569f..952390fe774b 100644 --- a/x/bank/client/cli/cli_test.go +++ b/x/bank/client/cli/cli_test.go @@ -32,12 +32,57 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") cfg := network.DefaultConfig() + genesisState := cfg.GenesisState cfg.NumValidators = 1 + var bankGenesis types.GenesisState + s.Require().NoError(cfg.Codec.UnmarshalJSON(genesisState[types.ModuleName], &bankGenesis)) + + bankGenesis.DenomMetadata = []types.Metadata{ + { + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + { + Denom: "uatom", + Exponent: 0, + Aliases: []string{"microatom"}, + }, + { + Denom: "atom", + Exponent: 6, + Aliases: []string{"ATOM"}, + }, + }, + Base: "uatom", + Display: "atom", + }, + { + Description: "Ethereum mainnet token", + DenomUnits: []*types.DenomUnit{ + { + Denom: "wei", + Exponent: 0, + }, + { + Denom: "eth", + Exponent: 6, + Aliases: []string{"ETH"}, + }, + }, + Base: "wei", + Display: "eth", + }, + } + + bankGenesisBz, err := cfg.Codec.MarshalJSON(&bankGenesis) + s.Require().NoError(err) + genesisState[types.ModuleName] = bankGenesisBz + cfg.GenesisState = genesisState + s.cfg = cfg s.network = network.New(s.T(), cfg) - _, err := s.network.WaitForHeight(1) + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) } @@ -181,6 +226,127 @@ func (s *IntegrationTestSuite) TestGetCmdQueryTotalSupply() { } } +func (s *IntegrationTestSuite) TestGetCmdQueryDenomsMetadata() { + val := s.network.Validators[0] + + testCases := []struct { + name string + args []string + expectErr bool + respType proto.Message + expected proto.Message + }{ + { + name: "all denoms client metadata", + args: []string{ + fmt.Sprintf("--%s=1", flags.FlagHeight), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + respType: &types.QueryDenomsMetadataResponse{}, + expected: &types.QueryDenomsMetadataResponse{ + Metadatas: []types.Metadata{ + { + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + { + Denom: "uatom", + Exponent: 0, + Aliases: []string{"microatom"}, + }, + { + Denom: "atom", + Exponent: 6, + Aliases: []string{"ATOM"}, + }, + }, + Base: "uatom", + Display: "atom", + }, + { + Description: "Ethereum mainnet token", + DenomUnits: []*types.DenomUnit{ + { + Denom: "wei", + Exponent: 0, + Aliases: []string{}, + }, + { + Denom: "eth", + Exponent: 6, + Aliases: []string{"ETH"}, + }, + }, + Base: "wei", + Display: "eth", + }, + }, + Pagination: &query.PageResponse{Total: 2}, + }, + }, + { + name: "client metadata of a specific denomination", + args: []string{ + fmt.Sprintf("--%s=1", flags.FlagHeight), + fmt.Sprintf("--%s=%s", cli.FlagDenom, "uatom"), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + respType: &types.QueryDenomMetadataResponse{}, + expected: &types.QueryDenomMetadataResponse{ + Metadata: types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + { + Denom: "uatom", + Exponent: 0, + Aliases: []string{"microatom"}, + }, + { + Denom: "atom", + Exponent: 6, + Aliases: []string{"ATOM"}, + }, + }, + Base: "uatom", + Display: "atom", + }, + }, + }, + { + name: "client metadata of a bogus denom", + args: []string{ + fmt.Sprintf("--%s=1", flags.FlagHeight), + fmt.Sprintf("--%s=foobar", cli.FlagDenom), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + expectErr: true, + respType: &types.QueryDenomMetadataResponse{}, + expected: &types.QueryDenomMetadataResponse{ + Metadata: types.Metadata{ + DenomUnits: []*types.DenomUnit{}, + }, + }, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdDenomsMetadata() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType)) + s.Require().Equal(tc.expected, tc.respType) + } + }) + } +} + func (s *IntegrationTestSuite) TestNewSendTxCmdGenOnly() { val := s.network.Validators[0] diff --git a/x/bank/client/cli/query.go b/x/bank/client/cli/query.go index 38badd7332d0..fbb9ba43825d 100644 --- a/x/bank/client/cli/query.go +++ b/x/bank/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "strings" @@ -33,6 +32,7 @@ func GetQueryCmd() *cobra.Command { cmd.AddCommand( GetBalancesCmd(), GetCmdQueryTotalSupply(), + GetCmdDenomsMetadata(), ) return cmd @@ -78,7 +78,7 @@ Example: if denom == "" { params := types.NewQueryAllBalancesRequest(addr, pageReq) - res, err := queryClient.AllBalances(context.Background(), params) + res, err := queryClient.AllBalances(cmd.Context(), params) if err != nil { return err } @@ -86,7 +86,7 @@ Example: } params := types.NewQueryBalanceRequest(addr, denom) - res, err := queryClient.Balance(context.Background(), params) + res, err := queryClient.Balance(cmd.Context(), params) if err != nil { return err } @@ -102,6 +102,60 @@ Example: return cmd } +// GetCmdDenomsMetadata defines the cobra command to query client denomination metadata. +func GetCmdDenomsMetadata() *cobra.Command { + cmd := &cobra.Command{ + Use: "denom-metadata", + Short: "Query the client metadata for coin denominations", + Long: strings.TrimSpace( + fmt.Sprintf(`Query the client metadata for all the registered coin denominations + +Example: + To query for the client metadata of all coin denominations use: + $ %s query %s denom-metadata + +To query for the client metadata of a specific coin denomination use: + $ %s query %s denom-metadata --denom=[denom] +`, + version.AppName, types.ModuleName, version.AppName, types.ModuleName, + ), + ), + RunE: func(cmd *cobra.Command, _ []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + denom, err := cmd.Flags().GetString(FlagDenom) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + + if denom == "" { + res, err := queryClient.DenomsMetadata(cmd.Context(), &types.QueryDenomsMetadataRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + } + + res, err := queryClient.DenomMetadata(cmd.Context(), &types.QueryDenomMetadataRequest{Denom: denom}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + cmd.Flags().String(FlagDenom, "", "The specific denomination to query client metadata for") + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + func GetCmdQueryTotalSupply() *cobra.Command { cmd := &cobra.Command{ Use: "total", @@ -131,7 +185,7 @@ To query for the total supply of a specific coin denomination use: queryClient := types.NewQueryClient(clientCtx) if denom == "" { - res, err := queryClient.TotalSupply(context.Background(), &types.QueryTotalSupplyRequest{}) + res, err := queryClient.TotalSupply(cmd.Context(), &types.QueryTotalSupplyRequest{}) if err != nil { return err } @@ -139,7 +193,7 @@ To query for the total supply of a specific coin denomination use: return clientCtx.PrintProto(res) } - res, err := queryClient.SupplyOf(context.Background(), &types.QuerySupplyOfRequest{Denom: denom}) + res, err := queryClient.SupplyOf(cmd.Context(), &types.QuerySupplyOfRequest{Denom: denom}) if err != nil { return err } diff --git a/x/bank/client/rest/grpc_query_test.go b/x/bank/client/rest/grpc_query_test.go index 6274946705ae..d6290a1fef94 100644 --- a/x/bank/client/rest/grpc_query_test.go +++ b/x/bank/client/rest/grpc_query_test.go @@ -98,6 +98,109 @@ func (s *IntegrationTestSuite) TestTotalSupplyGRPCHandler() { } } +func (s *IntegrationTestSuite) TestDenomMetadataGRPCHandler() { + val := s.network.Validators[0] + baseURL := val.APIAddress + + testCases := []struct { + name string + url string + headers map[string]string + expErr bool + respType proto.Message + expected proto.Message + }{ + { + "test GRPC client metadata", + fmt.Sprintf("%s/cosmos/bank/v1beta1/denoms_metadata", baseURL), + map[string]string{ + grpctypes.GRPCBlockHeightHeader: "1", + }, + false, + &types.QueryDenomsMetadataResponse{}, + &types.QueryDenomsMetadataResponse{ + Metadatas: []types.Metadata{ + { + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + { + Denom: "uatom", + Exponent: 0, + Aliases: []string{"microatom"}, + }, + { + Denom: "atom", + Exponent: 6, + Aliases: []string{"ATOM"}, + }, + }, + Base: "uatom", + Display: "atom", + }, + }, + Pagination: &query.PageResponse{Total: 1}, + }, + }, + { + "GRPC client metadata of a specific denom", + fmt.Sprintf("%s/cosmos/bank/v1beta1/denoms_metadata/uatom", baseURL), + map[string]string{ + grpctypes.GRPCBlockHeightHeader: "1", + }, + false, + &types.QueryDenomMetadataResponse{}, + &types.QueryDenomMetadataResponse{ + Metadata: types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + { + Denom: "uatom", + Exponent: 0, + Aliases: []string{"microatom"}, + }, + { + Denom: "atom", + Exponent: 6, + Aliases: []string{"ATOM"}, + }, + }, + Base: "uatom", + Display: "atom", + }, + }, + }, + { + "GRPC client metadata of a bogus denom", + fmt.Sprintf("%s/cosmos/bank/v1beta1/denoms_metadata/foobar", baseURL), + map[string]string{ + grpctypes.GRPCBlockHeightHeader: "1", + }, + true, + &types.QueryDenomMetadataResponse{}, + &types.QueryDenomMetadataResponse{ + Metadata: types.Metadata{ + DenomUnits: []*types.DenomUnit{}, + }, + }, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + resp, err := testutil.GetRequestWithHeaders(tc.url, tc.headers) + s.Require().NoError(err) + + if tc.expErr { + s.Require().Error(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) + } else { + s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) + s.Require().Equal(tc.expected.String(), tc.respType.String()) + } + }) + } +} + func (s *IntegrationTestSuite) TestBalancesGRPCHandler() { val := s.network.Validators[0] baseURL := val.APIAddress diff --git a/x/bank/client/rest/query_test.go b/x/bank/client/rest/query_test.go index 5ca3a15be506..11d731b6dcba 100644 --- a/x/bank/client/rest/query_test.go +++ b/x/bank/client/rest/query_test.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/rest" + "github.com/cosmos/cosmos-sdk/x/bank/types" ) type IntegrationTestSuite struct { @@ -24,12 +25,41 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") cfg := network.DefaultConfig() + genesisState := cfg.GenesisState cfg.NumValidators = 1 + var bankGenesis types.GenesisState + s.Require().NoError(cfg.Codec.UnmarshalJSON(genesisState[types.ModuleName], &bankGenesis)) + + bankGenesis.DenomMetadata = []types.Metadata{ + { + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + { + Denom: "uatom", + Exponent: 0, + Aliases: []string{"microatom"}, + }, + { + Denom: "atom", + Exponent: 6, + Aliases: []string{"ATOM"}, + }, + }, + Base: "uatom", + Display: "atom", + }, + } + + bankGenesisBz, err := cfg.Codec.MarshalJSON(&bankGenesis) + s.Require().NoError(err) + genesisState[types.ModuleName] = bankGenesisBz + cfg.GenesisState = genesisState + s.cfg = cfg s.network = network.New(s.T(), cfg) - _, err := s.network.WaitForHeight(2) + _, err = s.network.WaitForHeight(2) s.Require().NoError(err) } diff --git a/x/bank/keeper/genesis_test.go b/x/bank/keeper/genesis_test.go index bdb8cdc304e1..0e66da54e94d 100644 --- a/x/bank/keeper/genesis_test.go +++ b/x/bank/keeper/genesis_test.go @@ -44,13 +44,13 @@ func (suite *IntegrationTestSuite) getTestBalances() []types.Balance { } func (suite *IntegrationTestSuite) TestInitGenesis() { - require := suite.Require() m := types.Metadata{Description: sdk.DefaultBondDenom, Base: sdk.DefaultBondDenom, Display: sdk.DefaultBondDenom} g := types.DefaultGenesisState() g.DenomMetadata = []types.Metadata{m} bk := suite.app.BankKeeper bk.InitGenesis(suite.ctx, g) - m2 := bk.GetDenomMetaData(suite.ctx, m.Base) - require.Equal(m, m2) + m2, found := bk.GetDenomMetaData(suite.ctx, m.Base) + suite.Require().True(found) + suite.Require().Equal(m, m2) } diff --git a/x/bank/keeper/grpc_query.go b/x/bank/keeper/grpc_query.go index bcf143b8aa14..ae00d1b8734a 100644 --- a/x/bank/keeper/grpc_query.go +++ b/x/bank/keeper/grpc_query.go @@ -61,7 +61,7 @@ func (k BaseKeeper) AllBalances(ctx context.Context, req *types.QueryAllBalances balancesStore := prefix.NewStore(store, types.BalancesPrefix) accountStore := prefix.NewStore(balancesStore, addr.Bytes()) - pageRes, err := query.Paginate(accountStore, req.Pagination, func(key []byte, value []byte) error { + pageRes, err := query.Paginate(accountStore, req.Pagination, func(_, value []byte) error { var result sdk.Coin err := k.cdc.UnmarshalBinaryBare(value, &result) if err != nil { @@ -113,3 +113,53 @@ func (k BaseKeeper) Params(ctx context.Context, req *types.QueryParamsRequest) ( return &types.QueryParamsResponse{Params: params}, nil } + +// DenomsMetadata implements Query/DenomsMetadata gRPC method. +func (k BaseKeeper) DenomsMetadata(c context.Context, req *types.QueryDenomsMetadataRequest) (*types.QueryDenomsMetadataResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(c) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.DenomMetadataPrefix) + + metadatas := []types.Metadata{} + pageRes, err := query.Paginate(store, req.Pagination, func(_, value []byte) error { + var metadata types.Metadata + k.cdc.MustUnmarshalBinaryBare(value, &metadata) + + metadatas = append(metadatas, metadata) + return nil + }) + + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.QueryDenomsMetadataResponse{ + Metadatas: metadatas, + Pagination: pageRes, + }, nil +} + +// DenomMetadata implements Query/DenomMetadata gRPC method. +func (k BaseKeeper) DenomMetadata(c context.Context, req *types.QueryDenomMetadataRequest) (*types.QueryDenomMetadataResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + if req.Denom == "" { + return nil, status.Error(codes.InvalidArgument, "invalid denom") + } + + ctx := sdk.UnwrapSDKContext(c) + + metadata, found := k.GetDenomMetaData(ctx, req.Denom) + if !found { + return nil, status.Errorf(codes.NotFound, "client metadata for denom %s", req.Denom) + } + + return &types.QueryDenomMetadataResponse{ + Metadata: metadata, + }, nil +} diff --git a/x/bank/keeper/grpc_query_test.go b/x/bank/keeper/grpc_query_test.go index 27c29fd9e730..e178f1301751 100644 --- a/x/bank/keeper/grpc_query_test.go +++ b/x/bank/keeper/grpc_query_test.go @@ -4,6 +4,7 @@ package keeper_test import ( gocontext "context" + "fmt" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" @@ -119,3 +120,182 @@ func (suite *IntegrationTestSuite) TestQueryParams() { suite.Require().NotNil(res) suite.Require().Equal(suite.app.BankKeeper.GetParams(suite.ctx), res.GetParams()) } + +func (suite *IntegrationTestSuite) QueryDenomsMetadataRequest() { + var ( + req *types.QueryDenomsMetadataRequest + expMetadata = []types.Metadata{} + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + { + "empty pagination", + func() { + req = &types.QueryDenomsMetadataRequest{} + }, + true, + }, + { + "success, no results", + func() { + req = &types.QueryDenomsMetadataRequest{ + Pagination: &query.PageRequest{ + Limit: 3, + CountTotal: true, + }, + } + }, + true, + }, + { + "success", + func() { + metadataAtom := types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + { + Denom: "uatom", + Exponent: 0, + Aliases: []string{"microatom"}, + }, + { + Denom: "atom", + Exponent: 6, + Aliases: []string{"ATOM"}, + }, + }, + Base: "uatom", + Display: "atom", + } + + metadataEth := types.Metadata{ + Description: "Ethereum native token", + DenomUnits: []*types.DenomUnit{ + { + Denom: "wei", + Exponent: 0, + }, + { + Denom: "eth", + Exponent: 18, + Aliases: []string{"ETH", "ether"}, + }, + }, + Base: "wei", + Display: "eth", + } + + suite.app.BankKeeper.SetDenomMetaData(suite.ctx, metadataAtom) + suite.app.BankKeeper.SetDenomMetaData(suite.ctx, metadataEth) + expMetadata = []types.Metadata{metadataAtom, metadataEth} + req = &types.QueryDenomsMetadataRequest{ + Pagination: &query.PageRequest{ + Limit: 7, + CountTotal: true, + }, + } + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + ctx := sdk.WrapSDKContext(suite.ctx) + + res, err := suite.queryClient.DenomsMetadata(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + suite.Require().Equal(expMetadata, res.Metadatas) + } else { + suite.Require().Error(err) + } + }) + } +} + +func (suite *IntegrationTestSuite) QueryDenomMetadataRequest() { + var ( + req *types.QueryDenomMetadataRequest + expMetadata = types.Metadata{} + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + { + "empty denom", + func() { + req = &types.QueryDenomMetadataRequest{} + }, + false, + }, + { + "not found denom", + func() { + req = &types.QueryDenomMetadataRequest{ + Denom: "foo", + } + }, + false, + }, + { + "success", + func() { + expMetadata := types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + { + Denom: "uatom", + Exponent: 0, + Aliases: []string{"microatom"}, + }, + { + Denom: "atom", + Exponent: 6, + Aliases: []string{"ATOM"}, + }, + }, + Base: "uatom", + Display: "atom", + } + + suite.app.BankKeeper.SetDenomMetaData(suite.ctx, expMetadata) + req = &types.QueryDenomMetadataRequest{ + Denom: expMetadata.Base, + } + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + ctx := sdk.WrapSDKContext(suite.ctx) + + res, err := suite.queryClient.DenomMetadata(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + suite.Require().Equal(expMetadata, res.Metadata) + } else { + suite.Require().Error(err) + } + }) + } +} diff --git a/x/bank/keeper/keeper.go b/x/bank/keeper/keeper.go index 016537221f89..e5f221e4e204 100644 --- a/x/bank/keeper/keeper.go +++ b/x/bank/keeper/keeper.go @@ -27,7 +27,7 @@ type Keeper interface { GetSupply(ctx sdk.Context) exported.SupplyI SetSupply(ctx sdk.Context, supply exported.SupplyI) - GetDenomMetaData(ctx sdk.Context, denom string) types.Metadata + GetDenomMetaData(ctx sdk.Context, denom string) (types.Metadata, bool) SetDenomMetaData(ctx sdk.Context, denomMetaData types.Metadata) IterateAllDenomMetaData(ctx sdk.Context, cb func(types.Metadata) bool) @@ -180,15 +180,19 @@ func (k BaseKeeper) SetSupply(ctx sdk.Context, supply exported.SupplyI) { } // GetDenomMetaData retrieves the denomination metadata -func (k BaseKeeper) GetDenomMetaData(ctx sdk.Context, denom string) types.Metadata { +func (k BaseKeeper) GetDenomMetaData(ctx sdk.Context, denom string) (types.Metadata, bool) { store := ctx.KVStore(k.storeKey) store = prefix.NewStore(store, types.DenomMetadataKey(denom)) bz := store.Get([]byte(denom)) + if bz == nil { + return types.Metadata{}, false + } + var metadata types.Metadata k.cdc.MustUnmarshalBinaryBare(bz, &metadata) - return metadata + return metadata, true } // GetAllDenomMetaData retrieves all denominations metadata diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index 2f5c5055d2c8..80b4b070c278 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -981,8 +981,8 @@ func (suite *IntegrationTestSuite) TestSetDenomMetaData() { app.BankKeeper.SetDenomMetaData(ctx, metadata[i]) } - actualMetadata := app.BankKeeper.GetDenomMetaData(ctx, metadata[1].Base) - + actualMetadata, found := app.BankKeeper.GetDenomMetaData(ctx, metadata[1].Base) + suite.Require().True(found) suite.Require().Equal(metadata[1].GetBase(), actualMetadata.GetBase()) suite.Require().Equal(metadata[1].GetDisplay(), actualMetadata.GetDisplay()) suite.Require().Equal(metadata[1].GetDescription(), actualMetadata.GetDescription()) diff --git a/x/bank/types/errors.go b/x/bank/types/errors.go index dce69d0ac6bf..ab88b40e9b1d 100644 --- a/x/bank/types/errors.go +++ b/x/bank/types/errors.go @@ -6,8 +6,9 @@ import ( // x/bank module sentinel errors var ( - ErrNoInputs = sdkerrors.Register(ModuleName, 2, "no inputs to send transaction") - ErrNoOutputs = sdkerrors.Register(ModuleName, 3, "no outputs to send transaction") - ErrInputOutputMismatch = sdkerrors.Register(ModuleName, 4, "sum inputs != sum outputs") - ErrSendDisabled = sdkerrors.Register(ModuleName, 5, "send transactions are disabled") + ErrNoInputs = sdkerrors.Register(ModuleName, 2, "no inputs to send transaction") + ErrNoOutputs = sdkerrors.Register(ModuleName, 3, "no outputs to send transaction") + ErrInputOutputMismatch = sdkerrors.Register(ModuleName, 4, "sum inputs != sum outputs") + ErrSendDisabled = sdkerrors.Register(ModuleName, 5, "send transactions are disabled") + ErrDenomMetadataNotFound = sdkerrors.Register(ModuleName, 6, "client denom metadata not found") ) diff --git a/x/bank/types/query.pb.go b/x/bank/types/query.pb.go index 8d07c80787fc..c4bedb0098c5 100644 --- a/x/bank/types/query.pb.go +++ b/x/bank/types/query.pb.go @@ -475,6 +475,201 @@ func (m *QueryParamsResponse) GetParams() Params { return Params{} } +// QueryDenomsMetadataRequest is the request type for the Query/DenomsMetadata RPC method. +type QueryDenomsMetadataRequest struct { + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryDenomsMetadataRequest) Reset() { *m = QueryDenomsMetadataRequest{} } +func (m *QueryDenomsMetadataRequest) String() string { return proto.CompactTextString(m) } +func (*QueryDenomsMetadataRequest) ProtoMessage() {} +func (*QueryDenomsMetadataRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_9c6fc1939682df13, []int{10} +} +func (m *QueryDenomsMetadataRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryDenomsMetadataRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryDenomsMetadataRequest.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 *QueryDenomsMetadataRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryDenomsMetadataRequest.Merge(m, src) +} +func (m *QueryDenomsMetadataRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryDenomsMetadataRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryDenomsMetadataRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryDenomsMetadataRequest proto.InternalMessageInfo + +func (m *QueryDenomsMetadataRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata RPC +// method. +type QueryDenomsMetadataResponse struct { + // metadata provides the client information for all the registered tokens. + Metadatas []Metadata `protobuf:"bytes,1,rep,name=metadatas,proto3" json:"metadatas"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryDenomsMetadataResponse) Reset() { *m = QueryDenomsMetadataResponse{} } +func (m *QueryDenomsMetadataResponse) String() string { return proto.CompactTextString(m) } +func (*QueryDenomsMetadataResponse) ProtoMessage() {} +func (*QueryDenomsMetadataResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9c6fc1939682df13, []int{11} +} +func (m *QueryDenomsMetadataResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryDenomsMetadataResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryDenomsMetadataResponse.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 *QueryDenomsMetadataResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryDenomsMetadataResponse.Merge(m, src) +} +func (m *QueryDenomsMetadataResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryDenomsMetadataResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryDenomsMetadataResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryDenomsMetadataResponse proto.InternalMessageInfo + +func (m *QueryDenomsMetadataResponse) GetMetadatas() []Metadata { + if m != nil { + return m.Metadatas + } + return nil +} + +func (m *QueryDenomsMetadataResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryDenomMetadataRequest is the request type for the Query/DenomMetadata RPC method. +type QueryDenomMetadataRequest struct { + // denom is the coin denom to query the metadata for. + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` +} + +func (m *QueryDenomMetadataRequest) Reset() { *m = QueryDenomMetadataRequest{} } +func (m *QueryDenomMetadataRequest) String() string { return proto.CompactTextString(m) } +func (*QueryDenomMetadataRequest) ProtoMessage() {} +func (*QueryDenomMetadataRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_9c6fc1939682df13, []int{12} +} +func (m *QueryDenomMetadataRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryDenomMetadataRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryDenomMetadataRequest.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 *QueryDenomMetadataRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryDenomMetadataRequest.Merge(m, src) +} +func (m *QueryDenomMetadataRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryDenomMetadataRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryDenomMetadataRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryDenomMetadataRequest proto.InternalMessageInfo + +func (m *QueryDenomMetadataRequest) GetDenom() string { + if m != nil { + return m.Denom + } + return "" +} + +// QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC +// method. +type QueryDenomMetadataResponse struct { + // metadata describes and provides all the client information for the requested token. + Metadata Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata"` +} + +func (m *QueryDenomMetadataResponse) Reset() { *m = QueryDenomMetadataResponse{} } +func (m *QueryDenomMetadataResponse) String() string { return proto.CompactTextString(m) } +func (*QueryDenomMetadataResponse) ProtoMessage() {} +func (*QueryDenomMetadataResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9c6fc1939682df13, []int{13} +} +func (m *QueryDenomMetadataResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryDenomMetadataResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryDenomMetadataResponse.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 *QueryDenomMetadataResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryDenomMetadataResponse.Merge(m, src) +} +func (m *QueryDenomMetadataResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryDenomMetadataResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryDenomMetadataResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryDenomMetadataResponse proto.InternalMessageInfo + +func (m *QueryDenomMetadataResponse) GetMetadata() Metadata { + if m != nil { + return m.Metadata + } + return Metadata{} +} + func init() { proto.RegisterType((*QueryBalanceRequest)(nil), "cosmos.bank.v1beta1.QueryBalanceRequest") proto.RegisterType((*QueryBalanceResponse)(nil), "cosmos.bank.v1beta1.QueryBalanceResponse") @@ -486,55 +681,68 @@ func init() { proto.RegisterType((*QuerySupplyOfResponse)(nil), "cosmos.bank.v1beta1.QuerySupplyOfResponse") proto.RegisterType((*QueryParamsRequest)(nil), "cosmos.bank.v1beta1.QueryParamsRequest") proto.RegisterType((*QueryParamsResponse)(nil), "cosmos.bank.v1beta1.QueryParamsResponse") + proto.RegisterType((*QueryDenomsMetadataRequest)(nil), "cosmos.bank.v1beta1.QueryDenomsMetadataRequest") + proto.RegisterType((*QueryDenomsMetadataResponse)(nil), "cosmos.bank.v1beta1.QueryDenomsMetadataResponse") + proto.RegisterType((*QueryDenomMetadataRequest)(nil), "cosmos.bank.v1beta1.QueryDenomMetadataRequest") + proto.RegisterType((*QueryDenomMetadataResponse)(nil), "cosmos.bank.v1beta1.QueryDenomMetadataResponse") } func init() { proto.RegisterFile("cosmos/bank/v1beta1/query.proto", fileDescriptor_9c6fc1939682df13) } var fileDescriptor_9c6fc1939682df13 = []byte{ - // 675 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0x31, 0x6f, 0xd3, 0x40, - 0x14, 0xf6, 0x15, 0x9a, 0x96, 0xcb, 0x76, 0x0d, 0x22, 0x75, 0xc1, 0x41, 0xae, 0xa0, 0x49, 0x69, - 0x7d, 0x24, 0x1d, 0x2a, 0xd8, 0x48, 0x25, 0x18, 0x18, 0x1a, 0x0c, 0x13, 0xdb, 0x25, 0x39, 0x8c, - 0x55, 0xc7, 0xe7, 0xe6, 0x1c, 0x44, 0x54, 0x55, 0x20, 0x24, 0x24, 0x26, 0x40, 0x62, 0x60, 0x60, - 0xe9, 0xcc, 0x2f, 0xe9, 0xc0, 0x50, 0x89, 0x85, 0x09, 0x50, 0x02, 0x12, 0x3f, 0x03, 0xe5, 0xee, - 0x6c, 0x9c, 0xc6, 0x75, 0xb2, 0x30, 0xc5, 0xf7, 0xee, 0xbd, 0xef, 0x7d, 0xdf, 0xbb, 0xef, 0x2e, - 0xb0, 0xd4, 0x62, 0xbc, 0xc3, 0x38, 0x6e, 0x12, 0x7f, 0x0f, 0x3f, 0xab, 0x36, 0x69, 0x48, 0xaa, - 0x78, 0xbf, 0x47, 0xbb, 0x7d, 0x2b, 0xe8, 0xb2, 0x90, 0xa1, 0x25, 0x99, 0x60, 0x8d, 0x12, 0x2c, - 0x95, 0xa0, 0xaf, 0xc7, 0x55, 0x9c, 0xca, 0xec, 0xb8, 0x36, 0x20, 0x8e, 0xeb, 0x93, 0xd0, 0x65, - 0xbe, 0x04, 0xd0, 0x0b, 0x0e, 0x73, 0x98, 0xf8, 0xc4, 0xa3, 0x2f, 0x15, 0xbd, 0xec, 0x30, 0xe6, - 0x78, 0x14, 0x93, 0xc0, 0xc5, 0xc4, 0xf7, 0x59, 0x28, 0x4a, 0xb8, 0xda, 0x35, 0x92, 0xf8, 0x11, - 0x72, 0x8b, 0xb9, 0xfe, 0xc4, 0x7e, 0x82, 0xb5, 0x60, 0x28, 0xf6, 0xcd, 0x5d, 0xb8, 0xf4, 0x60, - 0xc4, 0xaa, 0x4e, 0x3c, 0xe2, 0xb7, 0xa8, 0x4d, 0xf7, 0x7b, 0x94, 0x87, 0xa8, 0x08, 0x17, 0x48, - 0xbb, 0xdd, 0xa5, 0x9c, 0x17, 0xc1, 0x55, 0x50, 0xbe, 0x60, 0x47, 0x4b, 0x54, 0x80, 0xf3, 0x6d, - 0xea, 0xb3, 0x4e, 0x71, 0x4e, 0xc4, 0xe5, 0xe2, 0xf6, 0xe2, 0x9b, 0xa3, 0x92, 0xf6, 0xe7, 0xa8, - 0xa4, 0x99, 0xf7, 0x61, 0x61, 0x1c, 0x90, 0x07, 0xcc, 0xe7, 0x14, 0x6d, 0xc1, 0x85, 0xa6, 0x0c, - 0x09, 0xc4, 0x7c, 0x6d, 0xd9, 0x8a, 0xe7, 0xc5, 0x69, 0x34, 0x2f, 0x6b, 0x87, 0xb9, 0xbe, 0x1d, - 0x65, 0x9a, 0xaf, 0x01, 0xbc, 0x24, 0xd0, 0xee, 0x78, 0x9e, 0x02, 0xe4, 0xd3, 0x29, 0xde, 0x85, - 0xf0, 0xdf, 0x6c, 0x05, 0xcf, 0x7c, 0xed, 0xfa, 0x58, 0x37, 0x79, 0x6c, 0x51, 0xcf, 0x06, 0x71, - 0x22, 0xe1, 0x76, 0xa2, 0x32, 0x21, 0xea, 0x0b, 0x80, 0xc5, 0x49, 0x1e, 0x4a, 0x99, 0x03, 0x17, - 0x15, 0xdf, 0x11, 0x93, 0x73, 0x99, 0xd2, 0xea, 0x37, 0x8f, 0xbf, 0x97, 0xb4, 0xcf, 0x3f, 0x4a, - 0x65, 0xc7, 0x0d, 0x9f, 0xf6, 0x9a, 0x56, 0x8b, 0x75, 0xb0, 0x3a, 0x22, 0xf9, 0xb3, 0xc9, 0xdb, - 0x7b, 0x38, 0xec, 0x07, 0x94, 0x8b, 0x02, 0x6e, 0xc7, 0xe0, 0xe8, 0x5e, 0x8a, 0xae, 0xb5, 0xa9, - 0xba, 0x24, 0xcb, 0xa4, 0x30, 0x73, 0x59, 0x4d, 0xf5, 0x11, 0x0b, 0x89, 0xf7, 0xb0, 0x17, 0x04, - 0x5e, 0x5f, 0xe9, 0x37, 0x5f, 0x28, 0xa1, 0x63, 0x5b, 0x4a, 0x68, 0x0b, 0xe6, 0xb8, 0x88, 0xfc, - 0x0f, 0x99, 0x0a, 0xda, 0xdc, 0x50, 0xfe, 0x91, 0xbd, 0x77, 0x9f, 0x44, 0xc7, 0x1d, 0xfb, 0x0e, - 0x24, 0x7c, 0x67, 0x36, 0xe0, 0xc5, 0x53, 0xd9, 0x8a, 0xeb, 0x36, 0xcc, 0x91, 0x0e, 0xeb, 0xf9, - 0xe1, 0x54, 0xb7, 0xd5, 0xcf, 0x8f, 0xb8, 0xda, 0x2a, 0xdd, 0x2c, 0x40, 0x24, 0x10, 0x1b, 0xa4, - 0x4b, 0x3a, 0x91, 0xd9, 0xcc, 0x86, 0xba, 0x26, 0x51, 0x54, 0x75, 0xb9, 0x05, 0x73, 0x81, 0x88, - 0xa8, 0x2e, 0x2b, 0x56, 0xca, 0x1b, 0x60, 0xc9, 0xa2, 0xa8, 0x8f, 0x2c, 0xa8, 0xfd, 0x9e, 0x87, - 0xf3, 0x02, 0x12, 0x7d, 0x04, 0x70, 0x41, 0x99, 0x0a, 0x95, 0x53, 0x01, 0x52, 0x6e, 0xa8, 0x5e, - 0x99, 0x21, 0x53, 0xb2, 0x34, 0xb7, 0x5f, 0x7d, 0xfd, 0xf5, 0x61, 0xae, 0x8a, 0x30, 0x4e, 0x7f, - 0x0c, 0xa4, 0xbd, 0xf0, 0x81, 0xba, 0x3f, 0x87, 0xf8, 0x40, 0x0c, 0xf7, 0x10, 0x7d, 0x02, 0x30, - 0x9f, 0x70, 0x3c, 0xda, 0x38, 0xbb, 0xe7, 0xe4, 0x05, 0xd5, 0x37, 0x67, 0xcc, 0x56, 0x2c, 0xb1, - 0x60, 0x59, 0x41, 0x6b, 0x33, 0xb2, 0x44, 0xef, 0x00, 0xcc, 0x27, 0x6c, 0x9a, 0xc5, 0x6e, 0xd2, - 0xe8, 0x59, 0xec, 0x52, 0xbc, 0x6f, 0xae, 0x0a, 0x76, 0x57, 0xd0, 0x4a, 0x2a, 0x3b, 0xe9, 0x5d, - 0xf4, 0x16, 0xc0, 0xc5, 0xc8, 0x89, 0x28, 0xe3, 0x80, 0x4e, 0x79, 0x5b, 0x5f, 0x9f, 0x25, 0x55, - 0x11, 0xb9, 0x21, 0x88, 0x5c, 0x43, 0xab, 0x19, 0x44, 0xe2, 0x03, 0x7c, 0x09, 0x60, 0x4e, 0xba, - 0x0f, 0xad, 0x9d, 0xdd, 0x63, 0xcc, 0xea, 0x7a, 0x79, 0x7a, 0xe2, 0x4c, 0x33, 0x91, 0x3e, 0xaf, - 0xef, 0x1c, 0x0f, 0x0c, 0x70, 0x32, 0x30, 0xc0, 0xcf, 0x81, 0x01, 0xde, 0x0f, 0x0d, 0xed, 0x64, - 0x68, 0x68, 0xdf, 0x86, 0x86, 0xf6, 0xb8, 0x92, 0xf9, 0x36, 0x3c, 0x97, 0x68, 0xe2, 0x89, 0x68, - 0xe6, 0xc4, 0x9f, 0xd5, 0xd6, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x31, 0x99, 0x37, 0x9b, 0x84, - 0x07, 0x00, 0x00, + // 824 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xcf, 0x6b, 0x13, 0x5b, + 0x14, 0xce, 0xed, 0x7b, 0x4d, 0xd3, 0x13, 0xde, 0x5b, 0xdc, 0xe6, 0xf1, 0xd2, 0xe9, 0x6b, 0xf2, + 0x98, 0x6a, 0x9b, 0xd6, 0x74, 0xa6, 0x69, 0x85, 0xa2, 0x1b, 0x69, 0x2a, 0xba, 0x10, 0x69, 0x8c, + 0xae, 0x04, 0x91, 0x9b, 0x64, 0x1c, 0x43, 0x93, 0xb9, 0xd3, 0xdc, 0x89, 0x58, 0x4a, 0x51, 0x04, + 0xc1, 0x95, 0x0a, 0x2e, 0x5c, 0xb8, 0xa9, 0x1b, 0x41, 0x97, 0xfe, 0x15, 0x5d, 0xb8, 0x28, 0xb8, + 0x71, 0xa5, 0xd2, 0xba, 0xf0, 0xcf, 0x90, 0xdc, 0x1f, 0xd3, 0x49, 0x32, 0x4d, 0x06, 0xd1, 0x55, + 0x66, 0xee, 0x3d, 0xe7, 0x3b, 0xdf, 0x77, 0xee, 0xb9, 0xdf, 0x04, 0xb2, 0x55, 0xca, 0x9a, 0x94, + 0x99, 0x15, 0xe2, 0x6c, 0x9a, 0xf7, 0x0a, 0x15, 0xcb, 0x23, 0x05, 0x73, 0xab, 0x6d, 0xb5, 0xb6, + 0x0d, 0xb7, 0x45, 0x3d, 0x8a, 0x27, 0x44, 0x80, 0xd1, 0x09, 0x30, 0x64, 0x80, 0xb6, 0xe0, 0x67, + 0x31, 0x4b, 0x44, 0xfb, 0xb9, 0x2e, 0xb1, 0xeb, 0x0e, 0xf1, 0xea, 0xd4, 0x11, 0x00, 0x5a, 0xca, + 0xa6, 0x36, 0xe5, 0x8f, 0x66, 0xe7, 0x49, 0xae, 0xfe, 0x67, 0x53, 0x6a, 0x37, 0x2c, 0x93, 0xb8, + 0x75, 0x93, 0x38, 0x0e, 0xf5, 0x78, 0x0a, 0x93, 0xbb, 0x99, 0x20, 0xbe, 0x42, 0xae, 0xd2, 0xba, + 0xd3, 0xb7, 0x1f, 0x60, 0xcd, 0x19, 0xf2, 0x7d, 0x7d, 0x03, 0x26, 0xae, 0x75, 0x58, 0x15, 0x49, + 0x83, 0x38, 0x55, 0xab, 0x6c, 0x6d, 0xb5, 0x2d, 0xe6, 0xe1, 0x34, 0x8c, 0x91, 0x5a, 0xad, 0x65, + 0x31, 0x96, 0x46, 0xff, 0xa3, 0xdc, 0x78, 0x59, 0xbd, 0xe2, 0x14, 0x8c, 0xd6, 0x2c, 0x87, 0x36, + 0xd3, 0x23, 0x7c, 0x5d, 0xbc, 0x9c, 0x4f, 0x3c, 0xd9, 0xcb, 0xc6, 0xbe, 0xef, 0x65, 0x63, 0xfa, + 0x15, 0x48, 0x75, 0x03, 0x32, 0x97, 0x3a, 0xcc, 0xc2, 0x2b, 0x30, 0x56, 0x11, 0x4b, 0x1c, 0x31, + 0xb9, 0x3c, 0x69, 0xf8, 0xfd, 0x62, 0x96, 0xea, 0x97, 0xb1, 0x4e, 0xeb, 0x4e, 0x59, 0x45, 0xea, + 0x8f, 0x11, 0xfc, 0xcb, 0xd1, 0xd6, 0x1a, 0x0d, 0x09, 0xc8, 0x86, 0x53, 0xbc, 0x04, 0x70, 0xdc, + 0x5b, 0xce, 0x33, 0xb9, 0x3c, 0xdb, 0x55, 0x4d, 0x1c, 0x9b, 0xaa, 0x59, 0x22, 0xb6, 0x12, 0x5e, + 0x0e, 0x64, 0x06, 0x44, 0x7d, 0x40, 0x90, 0xee, 0xe7, 0x21, 0x95, 0xd9, 0x90, 0x90, 0x7c, 0x3b, + 0x4c, 0xfe, 0x18, 0x28, 0xad, 0xb8, 0xb4, 0xff, 0x39, 0x1b, 0x7b, 0xf7, 0x25, 0x9b, 0xb3, 0xeb, + 0xde, 0xdd, 0x76, 0xc5, 0xa8, 0xd2, 0xa6, 0x29, 0x8f, 0x48, 0xfc, 0x2c, 0xb2, 0xda, 0xa6, 0xe9, + 0x6d, 0xbb, 0x16, 0xe3, 0x09, 0xac, 0xec, 0x83, 0xe3, 0xcb, 0x21, 0xba, 0xe6, 0x86, 0xea, 0x12, + 0x2c, 0x83, 0xc2, 0xf4, 0x49, 0xd9, 0xd5, 0x1b, 0xd4, 0x23, 0x8d, 0xeb, 0x6d, 0xd7, 0x6d, 0x6c, + 0x4b, 0xfd, 0xfa, 0x03, 0x29, 0xb4, 0x6b, 0x4b, 0x0a, 0xad, 0x42, 0x9c, 0xf1, 0x95, 0xdf, 0x21, + 0x53, 0x42, 0xeb, 0x79, 0x39, 0x3f, 0xa2, 0xf6, 0xc6, 0x1d, 0x75, 0xdc, 0xfe, 0xdc, 0xa1, 0xc0, + 0xdc, 0xe9, 0x25, 0xf8, 0xa7, 0x27, 0x5a, 0x72, 0x5d, 0x85, 0x38, 0x69, 0xd2, 0xb6, 0xe3, 0x0d, + 0x9d, 0xb6, 0xe2, 0x9f, 0x1d, 0xae, 0x65, 0x19, 0xae, 0xa7, 0x00, 0x73, 0xc4, 0x12, 0x69, 0x91, + 0xa6, 0x1a, 0x36, 0xbd, 0x24, 0xaf, 0x89, 0x5a, 0x95, 0x55, 0xce, 0x41, 0xdc, 0xe5, 0x2b, 0xb2, + 0xca, 0x94, 0x11, 0xe2, 0x01, 0x86, 0x48, 0x52, 0x75, 0x44, 0x82, 0x5e, 0x03, 0x8d, 0x23, 0x5e, + 0xec, 0xe8, 0x60, 0x57, 0x2d, 0x8f, 0xd4, 0x88, 0x47, 0x94, 0xda, 0xee, 0x11, 0x46, 0x3f, 0x3b, + 0xc2, 0xfa, 0x5b, 0x04, 0x53, 0xa1, 0x65, 0xa4, 0x80, 0x35, 0x18, 0x6f, 0xca, 0x35, 0x35, 0xbc, + 0xd3, 0xa1, 0x1a, 0x54, 0xa6, 0x54, 0x71, 0x9c, 0xf5, 0xeb, 0xa6, 0xb2, 0x00, 0x93, 0xc7, 0x54, + 0x7b, 0x1b, 0x12, 0x7e, 0xfc, 0xb7, 0x82, 0x4d, 0xec, 0x13, 0x77, 0x01, 0x12, 0x8a, 0xa6, 0x6c, + 0x61, 0x24, 0x6d, 0x7e, 0xd2, 0xf2, 0xfb, 0x04, 0x8c, 0x72, 0x7c, 0xfc, 0x12, 0xc1, 0x98, 0xbc, + 0xf8, 0x38, 0x17, 0x0a, 0x12, 0xe2, 0xa2, 0xda, 0x7c, 0x84, 0x48, 0xc1, 0x55, 0x5f, 0x7d, 0xf4, + 0xf1, 0xdb, 0x8b, 0x91, 0x02, 0x36, 0xcd, 0x70, 0xc3, 0x16, 0x16, 0x60, 0xee, 0x48, 0x8f, 0xdb, + 0x35, 0x77, 0x78, 0x07, 0x76, 0xf1, 0x2b, 0x04, 0xc9, 0x80, 0x2b, 0xe1, 0xfc, 0xc9, 0x35, 0xfb, + 0x4d, 0x54, 0x5b, 0x8c, 0x18, 0x2d, 0x59, 0x9a, 0x9c, 0xe5, 0x3c, 0x9e, 0x8b, 0xc8, 0x12, 0x3f, + 0x43, 0x90, 0x0c, 0x58, 0xc9, 0x20, 0x76, 0xfd, 0x66, 0x34, 0x88, 0x5d, 0x88, 0x3f, 0xe9, 0x33, + 0x9c, 0xdd, 0x34, 0x9e, 0x0a, 0x65, 0x27, 0xfc, 0x05, 0x3f, 0x45, 0x90, 0x50, 0x6e, 0x81, 0x07, + 0x1c, 0x50, 0x8f, 0xff, 0x68, 0x0b, 0x51, 0x42, 0x25, 0x91, 0x33, 0x9c, 0xc8, 0x69, 0x3c, 0x33, + 0x80, 0x88, 0x7f, 0x80, 0x0f, 0x11, 0xc4, 0x85, 0x43, 0xe0, 0xb9, 0x93, 0x6b, 0x74, 0xd9, 0x91, + 0x96, 0x1b, 0x1e, 0x18, 0xa9, 0x27, 0xc2, 0x8b, 0xf0, 0x1b, 0x04, 0x7f, 0x75, 0x5d, 0x21, 0x6c, + 0x9c, 0x5c, 0x20, 0xec, 0x7a, 0x6a, 0x66, 0xe4, 0x78, 0xc9, 0xeb, 0x2c, 0xe7, 0x65, 0xe0, 0x7c, + 0x28, 0x2f, 0xde, 0x1a, 0x76, 0x5b, 0x5d, 0x44, 0xbf, 0x57, 0xaf, 0x11, 0xfc, 0xdd, 0xed, 0x64, + 0x78, 0x58, 0xe5, 0x5e, 0x6b, 0xd5, 0x96, 0xa2, 0x27, 0x48, 0xae, 0x79, 0xce, 0x75, 0x16, 0x9f, + 0x8a, 0xc2, 0xb5, 0xb8, 0xbe, 0x7f, 0x98, 0x41, 0x07, 0x87, 0x19, 0xf4, 0xf5, 0x30, 0x83, 0x9e, + 0x1f, 0x65, 0x62, 0x07, 0x47, 0x99, 0xd8, 0xa7, 0xa3, 0x4c, 0xec, 0xe6, 0xfc, 0xc0, 0x8f, 0xe1, + 0x7d, 0x01, 0xcb, 0xbf, 0x89, 0x95, 0x38, 0xff, 0x77, 0xb6, 0xf2, 0x23, 0x00, 0x00, 0xff, 0xff, + 0xb4, 0xd4, 0xb0, 0xfc, 0x75, 0x0a, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -559,6 +767,10 @@ type QueryClient interface { SupplyOf(ctx context.Context, in *QuerySupplyOfRequest, opts ...grpc.CallOption) (*QuerySupplyOfResponse, error) // Params queries the parameters of x/bank module. Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) + // DenomsMetadata queries the client metadata of a given coin denomination. + DenomMetadata(ctx context.Context, in *QueryDenomMetadataRequest, opts ...grpc.CallOption) (*QueryDenomMetadataResponse, error) + // DenomsMetadata queries the client metadata for all registered coin denominations. + DenomsMetadata(ctx context.Context, in *QueryDenomsMetadataRequest, opts ...grpc.CallOption) (*QueryDenomsMetadataResponse, error) } type queryClient struct { @@ -614,6 +826,24 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts . return out, nil } +func (c *queryClient) DenomMetadata(ctx context.Context, in *QueryDenomMetadataRequest, opts ...grpc.CallOption) (*QueryDenomMetadataResponse, error) { + out := new(QueryDenomMetadataResponse) + err := c.cc.Invoke(ctx, "/cosmos.bank.v1beta1.Query/DenomMetadata", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) DenomsMetadata(ctx context.Context, in *QueryDenomsMetadataRequest, opts ...grpc.CallOption) (*QueryDenomsMetadataResponse, error) { + out := new(QueryDenomsMetadataResponse) + err := c.cc.Invoke(ctx, "/cosmos.bank.v1beta1.Query/DenomsMetadata", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // Balance queries the balance of a single coin for a single account. @@ -626,6 +856,10 @@ type QueryServer interface { SupplyOf(context.Context, *QuerySupplyOfRequest) (*QuerySupplyOfResponse, error) // Params queries the parameters of x/bank module. Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) + // DenomsMetadata queries the client metadata of a given coin denomination. + DenomMetadata(context.Context, *QueryDenomMetadataRequest) (*QueryDenomMetadataResponse, error) + // DenomsMetadata queries the client metadata for all registered coin denominations. + DenomsMetadata(context.Context, *QueryDenomsMetadataRequest) (*QueryDenomsMetadataResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -647,6 +881,12 @@ func (*UnimplementedQueryServer) SupplyOf(ctx context.Context, req *QuerySupplyO func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") } +func (*UnimplementedQueryServer) DenomMetadata(ctx context.Context, req *QueryDenomMetadataRequest) (*QueryDenomMetadataResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DenomMetadata not implemented") +} +func (*UnimplementedQueryServer) DenomsMetadata(ctx context.Context, req *QueryDenomsMetadataRequest) (*QueryDenomsMetadataResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DenomsMetadata not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -742,6 +982,42 @@ func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interf return interceptor(ctx, in, info, handler) } +func _Query_DenomMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryDenomMetadataRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).DenomMetadata(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.bank.v1beta1.Query/DenomMetadata", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).DenomMetadata(ctx, req.(*QueryDenomMetadataRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_DenomsMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryDenomsMetadataRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).DenomsMetadata(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.bank.v1beta1.Query/DenomsMetadata", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).DenomsMetadata(ctx, req.(*QueryDenomsMetadataRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "cosmos.bank.v1beta1.Query", HandlerType: (*QueryServer)(nil), @@ -766,6 +1042,14 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "Params", Handler: _Query_Params_Handler, }, + { + MethodName: "DenomMetadata", + Handler: _Query_DenomMetadata_Handler, + }, + { + MethodName: "DenomsMetadata", + Handler: _Query_DenomsMetadata_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "cosmos/bank/v1beta1/query.proto", @@ -1113,81 +1397,228 @@ func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { - offset -= sovQuery(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *QueryBalanceRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Address) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.Denom) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) +func (m *QueryDenomsMetadataRequest) 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 n + return dAtA[:n], nil } -func (m *QueryBalanceResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Balance != nil { - l = m.Balance.Size() - n += 1 + l + sovQuery(uint64(l)) - } - return n +func (m *QueryDenomsMetadataRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryAllBalancesRequest) Size() (n int) { - if m == nil { - return 0 - } +func (m *QueryDenomsMetadataRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - l = len(m.Address) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } if m.Pagination != nil { - l = m.Pagination.Size() - n += 1 + l + sovQuery(uint64(l)) + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa } - return n + return len(dAtA) - i, nil } -func (m *QueryAllBalancesResponse) Size() (n int) { - if m == nil { - return 0 +func (m *QueryDenomsMetadataResponse) 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 *QueryDenomsMetadataResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryDenomsMetadataResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - if len(m.Balances) > 0 { - for _, e := range m.Balances { - l = e.Size() - n += 1 + l + sovQuery(uint64(l)) - } - } if m.Pagination != nil { - l = m.Pagination.Size() - n += 1 + l + sovQuery(uint64(l)) - } - return n + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Metadatas) > 0 { + for iNdEx := len(m.Metadatas) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Metadatas[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 *QueryDenomMetadataRequest) 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 *QueryDenomMetadataRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryDenomMetadataRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryDenomMetadataResponse) 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 *QueryDenomMetadataResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryDenomMetadataResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Metadata.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 encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryBalanceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryBalanceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Balance != nil { + l = m.Balance.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAllBalancesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAllBalancesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Balances) > 0 { + for _, e := range m.Balances { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n } func (m *QueryTotalSupplyRequest) Size() (n int) { @@ -1258,6 +1689,62 @@ func (m *QueryParamsResponse) Size() (n int) { return n } +func (m *QueryDenomsMetadataRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryDenomsMetadataResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Metadatas) > 0 { + for _, e := range m.Metadatas { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryDenomMetadataRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryDenomMetadataResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Metadata.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1352,11 +1839,385 @@ func (m *QueryBalanceRequest) Unmarshal(dAtA []byte) error { if postIndex < 0 { return ErrInvalidLengthQuery } - if postIndex > l { + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryBalanceResponse) 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: QueryBalanceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryBalanceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Balance", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Balance == nil { + m.Balance = &types.Coin{} + } + if err := m.Balance.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAllBalancesRequest) 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: QueryAllBalancesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAllBalancesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAllBalancesResponse) 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: QueryAllBalancesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAllBalancesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Balances", 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.Balances = append(m.Balances, types.Coin{}) + if err := m.Balances[len(m.Balances)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryTotalSupplyRequest) 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 } - m.Denom = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex + 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: QueryTotalSupplyRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryTotalSupplyRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -1378,7 +2239,7 @@ func (m *QueryBalanceRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryBalanceResponse) Unmarshal(dAtA []byte) error { +func (m *QueryTotalSupplyResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1401,15 +2262,15 @@ func (m *QueryBalanceResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryBalanceResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryTotalSupplyResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryBalanceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryTotalSupplyResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Balance", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Supply", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1436,10 +2297,8 @@ func (m *QueryBalanceResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Balance == nil { - m.Balance = &types.Coin{} - } - if err := m.Balance.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Supply = append(m.Supply, types.Coin{}) + if err := m.Supply[len(m.Supply)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -1464,7 +2323,7 @@ func (m *QueryBalanceResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryAllBalancesRequest) Unmarshal(dAtA []byte) error { +func (m *QuerySupplyOfRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1487,15 +2346,15 @@ func (m *QueryAllBalancesRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryAllBalancesRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QuerySupplyOfRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryAllBalancesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QuerySupplyOfRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1523,43 +2382,7 @@ func (m *QueryAllBalancesRequest) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Address = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Pagination == nil { - m.Pagination = &query.PageRequest{} - } - if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Denom = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -1582,7 +2405,7 @@ func (m *QueryAllBalancesRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryAllBalancesResponse) Unmarshal(dAtA []byte) error { +func (m *QuerySupplyOfResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1605,49 +2428,15 @@ func (m *QueryAllBalancesResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryAllBalancesResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QuerySupplyOfResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryAllBalancesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QuerySupplyOfResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Balances", 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.Balances = append(m.Balances, types.Coin{}) - if err := m.Balances[len(m.Balances)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1674,10 +2463,7 @@ func (m *QueryAllBalancesResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Pagination == nil { - m.Pagination = &query.PageResponse{} - } - if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -1702,7 +2488,7 @@ func (m *QueryAllBalancesResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryTotalSupplyRequest) Unmarshal(dAtA []byte) error { +func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1725,10 +2511,10 @@ func (m *QueryTotalSupplyRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryTotalSupplyRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryParamsRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryTotalSupplyRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -1752,7 +2538,7 @@ func (m *QueryTotalSupplyRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryTotalSupplyResponse) Unmarshal(dAtA []byte) error { +func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1775,15 +2561,15 @@ func (m *QueryTotalSupplyResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryTotalSupplyResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryParamsResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryTotalSupplyResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Supply", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1810,8 +2596,7 @@ func (m *QueryTotalSupplyResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Supply = append(m.Supply, types.Coin{}) - if err := m.Supply[len(m.Supply)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -1836,7 +2621,7 @@ func (m *QueryTotalSupplyResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QuerySupplyOfRequest) Unmarshal(dAtA []byte) error { +func (m *QueryDenomsMetadataRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1859,17 +2644,17 @@ func (m *QuerySupplyOfRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QuerySupplyOfRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryDenomsMetadataRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QuerySupplyOfRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryDenomsMetadataRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -1879,23 +2664,27 @@ func (m *QuerySupplyOfRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLengthQuery } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthQuery } if postIndex > l { return io.ErrUnexpectedEOF } - m.Denom = string(dAtA[iNdEx:postIndex]) + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex default: iNdEx = preIndex @@ -1918,7 +2707,7 @@ func (m *QuerySupplyOfRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QuerySupplyOfResponse) Unmarshal(dAtA []byte) error { +func (m *QueryDenomsMetadataResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1941,15 +2730,15 @@ func (m *QuerySupplyOfResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QuerySupplyOfResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryDenomsMetadataResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QuerySupplyOfResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryDenomsMetadataResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Metadatas", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1976,7 +2765,44 @@ func (m *QuerySupplyOfResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Metadatas = append(m.Metadatas, Metadata{}) + if err := m.Metadatas[len(m.Metadatas)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -2001,7 +2827,7 @@ func (m *QuerySupplyOfResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { +func (m *QueryDenomMetadataRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2024,12 +2850,44 @@ func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryParamsRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryDenomMetadataRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryDenomMetadataRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -2051,7 +2909,7 @@ func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { +func (m *QueryDenomMetadataResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2074,15 +2932,15 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryParamsResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryDenomMetadataResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryDenomMetadataResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -2109,7 +2967,7 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Metadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/x/bank/types/query.pb.gw.go b/x/bank/types/query.pb.gw.go index b1c6372ab7c1..06c7e2d04aa5 100644 --- a/x/bank/types/query.pb.gw.go +++ b/x/bank/types/query.pb.gw.go @@ -269,6 +269,96 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal } +func request_Query_DenomMetadata_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDenomMetadataRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["denom"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom") + } + + protoReq.Denom, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err) + } + + msg, err := client.DenomMetadata(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_DenomMetadata_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDenomMetadataRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["denom"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom") + } + + protoReq.Denom, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err) + } + + msg, err := server.DenomMetadata(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_DenomsMetadata_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_DenomsMetadata_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDenomsMetadataRequest + 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_DenomsMetadata_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.DenomsMetadata(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_DenomsMetadata_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryDenomsMetadataRequest + 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_DenomsMetadata_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.DenomsMetadata(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -375,6 +465,46 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_DenomMetadata_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_DenomMetadata_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DenomMetadata_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_DenomsMetadata_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_DenomsMetadata_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DenomsMetadata_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -516,6 +646,46 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_DenomMetadata_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_DenomMetadata_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_DenomMetadata_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_DenomsMetadata_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_DenomsMetadata_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_DenomsMetadata_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -529,6 +699,10 @@ var ( pattern_Query_SupplyOf_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "bank", "v1beta1", "supply", "denom"}, "", runtime.AssumeColonVerbOpt(true))) pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "bank", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_DenomMetadata_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "bank", "v1beta1", "denoms_metadata", "denom"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_DenomsMetadata_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "bank", "v1beta1", "denoms_metadata"}, "", runtime.AssumeColonVerbOpt(true))) ) var ( @@ -541,4 +715,8 @@ var ( forward_Query_SupplyOf_0 = runtime.ForwardResponseMessage forward_Query_Params_0 = runtime.ForwardResponseMessage + + forward_Query_DenomMetadata_0 = runtime.ForwardResponseMessage + + forward_Query_DenomsMetadata_0 = runtime.ForwardResponseMessage ) From 0460f98518e6d52e11e3c76805d78c2fb09c8b2a Mon Sep 17 00:00:00 2001 From: MD Aleem <72057206+aleem1314@users.noreply.github.com> Date: Mon, 18 Jan 2021 23:55:22 +0530 Subject: [PATCH 057/152] gRPC-web proxy (#8077) * init * WIP config * WIP add proxy server * fmt * WIP * setup proxy server * clean go.mod * lint * lint * lint * custom codec * lint * add comments * change grpc-proxy port * add grpc-web * update server/start.go * add tests * add test with client * Update server/start.go Co-authored-by: Anil Kumar Kammari * Update server/start.go Co-authored-by: Amaury * Update server/start.go Co-authored-by: Amaury * review changes * review changes * Update server/start.go Co-authored-by: Anil Kumar Kammari Co-authored-by: Amaury Co-authored-by: Aleksandr Bezobchuk Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- go.mod | 2 + go.sum | 9 + server/config/config.go | 23 ++- server/config/toml.go | 13 ++ server/grpc/grpc_web.go | 25 +++ server/grpc/grpc_web_test.go | 313 +++++++++++++++++++++++++++++++++++ server/start.go | 25 ++- testutil/network/network.go | 17 +- testutil/network/util.go | 18 ++ 9 files changed, 438 insertions(+), 7 deletions(-) create mode 100644 server/grpc/grpc_web.go create mode 100644 server/grpc/grpc_web_test.go diff --git a/go.mod b/go.mod index 10577caa095a..c507219f9663 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/iavl v0.15.3 github.com/cosmos/ledger-cosmos-go v0.11.1 + github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dgraph-io/ristretto v0.0.3 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 @@ -26,6 +27,7 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/hashicorp/golang-lru v0.5.4 + github.com/improbable-eng/grpc-web v0.13.0 github.com/magiconair/properties v1.8.4 github.com/mattn/go-isatty v0.0.12 github.com/otiai10/copy v1.4.2 diff --git a/go.sum b/go.sum index 30275e7ac493..aeab76d9c9e3 100644 --- a/go.sum +++ b/go.sum @@ -123,6 +123,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/dgraph-io/badger/v2 v2.2007.1/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= github.com/dgraph-io/badger/v2 v2.2007.2 h1:EjjK0KqwaFMlPin1ajhP943VPENHJdEz1KLIegjaI3k= github.com/dgraph-io/badger/v2 v2.2007.2/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= @@ -253,6 +255,7 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de github.com/grpc-ecosystem/go-grpc-middleware v1.2.1/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= @@ -299,6 +302,8 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/improbable-eng/grpc-web v0.13.0 h1:7XqtaBWaOCH0cVGKHyvhtcuo6fgW32Y10yRKrDHFHOc= +github.com/improbable-eng/grpc-web v0.13.0/go.mod h1:6hRR09jOEG81ADP5wCQju1z71g6OL4eEvELdran/3cs= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= @@ -308,6 +313,7 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -327,6 +333,7 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -373,6 +380,7 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= @@ -500,6 +508,7 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= diff --git a/server/config/config.go b/server/config/config.go index 80e79f04558d..68f6cf4352f6 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -14,8 +14,11 @@ import ( const ( defaultMinGasPrices = "" - // DefaultGRPCAddress is the default address the gRPC server binds to. + // DefaultGRPCAddress defines the default address to bind the gRPC server to. DefaultGRPCAddress = "0.0.0.0:9090" + + // DefaultGRPCWebAddress defines the default address to bind the gRPC-web server to. + DefaultGRPCWebAddress = "0.0.0.0:9091" ) // BaseConfig defines the server's basic configuration @@ -107,6 +110,15 @@ type GRPCConfig struct { Address string `mapstructure:"address"` } +// GRPCWebConfig defines configuration for the gRPC-web server. +type GRPCWebConfig struct { + // Enable defines if the gRPC-web should be enabled. + Enable bool `mapstructure:"enable"` + + // Address defines the gRPC-web server to listen on + Address string `mapstructure:"address"` +} + // StateSyncConfig defines the state sync snapshot configuration. type StateSyncConfig struct { // SnapshotInterval sets the interval at which state sync snapshots are taken. @@ -126,6 +138,7 @@ type Config struct { Telemetry telemetry.Config `mapstructure:"telemetry"` API APIConfig `mapstructure:"api"` GRPC GRPCConfig `mapstructure:"grpc"` + GRPCWeb GRPCWebConfig `mapstructure:"grpc-web"` StateSync StateSyncConfig `mapstructure:"state-sync"` } @@ -185,6 +198,10 @@ func DefaultConfig() *Config { Enable: true, Address: DefaultGRPCAddress, }, + GRPCWeb: GRPCWebConfig{ + Enable: true, + Address: DefaultGRPCWebAddress, + }, StateSync: StateSyncConfig{ SnapshotInterval: 0, SnapshotKeepRecent: 2, @@ -239,6 +256,10 @@ func GetConfig(v *viper.Viper) Config { Enable: v.GetBool("grpc.enable"), Address: v.GetString("grpc.address"), }, + GRPCWeb: GRPCWebConfig{ + Enable: v.GetBool("grpc-web.enable"), + Address: v.GetString("grpc-web.address"), + }, StateSync: StateSyncConfig{ SnapshotInterval: v.GetUint64("state-sync.snapshot-interval"), SnapshotKeepRecent: v.GetUint32("state-sync.snapshot-keep-recent"), diff --git a/server/config/toml.go b/server/config/toml.go index b042da74293d..58dc7bfed2b4 100644 --- a/server/config/toml.go +++ b/server/config/toml.go @@ -147,6 +147,19 @@ enable = {{ .GRPC.Enable }} # Address defines the gRPC server address to bind to. address = "{{ .GRPC.Address }}" +############################################################################### +### gRPC Web Configuration ### +############################################################################### + +[grpc-web] + +# GRPCWebEnable defines if the gRPC-web should be enabled. +# NOTE: gRPC must also be enabled, otherwise, this configuration is a no-op. +enable = {{ .GRPCWeb.Enable }} + +# Address defines the gRPC-web server address to bind to. +address = "{{ .GRPCWeb.Address }}" + ############################################################################### ### State Sync Configuration ### ############################################################################### diff --git a/server/grpc/grpc_web.go b/server/grpc/grpc_web.go new file mode 100644 index 000000000000..30c71808e43e --- /dev/null +++ b/server/grpc/grpc_web.go @@ -0,0 +1,25 @@ +package grpc + +import ( + "net/http" + + "github.com/cosmos/cosmos-sdk/server/config" + "github.com/improbable-eng/grpc-web/go/grpcweb" + "google.golang.org/grpc" +) + +// StartGRPCWeb starts a gRPC-Web server on the given address. +func StartGRPCWeb(grpcSrv *grpc.Server, config config.Config) (*http.Server, error) { + wrappedServer := grpcweb.WrapServer(grpcSrv) + handler := func(resp http.ResponseWriter, req *http.Request) { + wrappedServer.ServeHTTP(resp, req) + } + grpcWebSrv := &http.Server{ + Addr: config.GRPCWeb.Address, + Handler: http.HandlerFunc(handler), + } + if err := grpcWebSrv.ListenAndServe(); err != nil { + return nil, err + } + return grpcWebSrv, nil +} diff --git a/server/grpc/grpc_web_test.go b/server/grpc/grpc_web_test.go new file mode 100644 index 000000000000..8f563becc666 --- /dev/null +++ b/server/grpc/grpc_web_test.go @@ -0,0 +1,313 @@ +package grpc_test + +import ( + "bufio" + "bytes" + "encoding/base64" + "encoding/binary" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/textproto" + "strconv" + "strings" + "testing" + + "github.com/golang/protobuf/proto" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "google.golang.org/grpc/codes" + + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" + "github.com/cosmos/cosmos-sdk/codec" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/testutil/network" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +// https://github.com/improbable-eng/grpc-web/blob/master/go/grpcweb/wrapper_test.go used as a reference +// to setup grpcRequest config. + +const grpcWebContentType = "application/grpc-web" + +type GRPCWebTestSuite struct { + suite.Suite + + cfg network.Config + network *network.Network + protoCdc *codec.ProtoCodec +} + +func (s *GRPCWebTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + s.cfg = cfg + s.network = network.New(s.T(), s.cfg) + s.Require().NotNil(s.network) + + _, err := s.network.WaitForHeight(2) + s.Require().NoError(err) + + s.protoCdc = codec.NewProtoCodec(s.cfg.InterfaceRegistry) +} + +func (s *GRPCWebTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +func (s *GRPCWebTestSuite) Test_Latest_Validators() { + val := s.network.Validators[0] + for _, contentType := range []string{grpcWebContentType} { + headers, trailers, responses, err := s.makeGrpcRequest( + "/cosmos.base.tendermint.v1beta1.Service/GetLatestValidatorSet", + headerWithFlag(), + serializeProtoMessages([]proto.Message{&tmservice.GetLatestValidatorSetRequest{}}), false) + + s.Require().NoError(err) + s.Require().Equal(1, len(responses)) + s.assertTrailerGrpcCode(trailers, codes.OK, "") + s.assertContentTypeSet(headers, contentType) + var valsSet tmservice.GetLatestValidatorSetResponse + err = s.protoCdc.UnmarshalBinaryBare(responses[0], &valsSet) + s.Require().NoError(err) + pubKey, ok := valsSet.Validators[0].PubKey.GetCachedValue().(cryptotypes.PubKey) + s.Require().Equal(true, ok) + s.Require().Equal(pubKey, val.PubKey) + } +} + +func (s *GRPCWebTestSuite) Test_Total_Supply() { + for _, contentType := range []string{grpcWebContentType} { + headers, trailers, responses, err := s.makeGrpcRequest( + "/cosmos.bank.v1beta1.Query/TotalSupply", + headerWithFlag(), + serializeProtoMessages([]proto.Message{&banktypes.QueryTotalSupplyRequest{}}), false) + + s.Require().NoError(err) + s.Require().Equal(1, len(responses)) + s.assertTrailerGrpcCode(trailers, codes.OK, "") + s.assertContentTypeSet(headers, contentType) + var totalSupply banktypes.QueryTotalSupplyResponse + _ = s.protoCdc.UnmarshalBinaryBare(responses[0], &totalSupply) + } +} + +func (s *GRPCWebTestSuite) assertContentTypeSet(headers http.Header, contentType string) { + s.Require().Equal(contentType, headers.Get("content-type"), `Expected there to be content-type=%v`, contentType) +} + +func (s *GRPCWebTestSuite) assertTrailerGrpcCode(trailers Trailer, code codes.Code, desc string) { + s.Require().NotEmpty(trailers.Get("grpc-status"), "grpc-status must not be empty in trailers") + statusCode, err := strconv.Atoi(trailers.Get("grpc-status")) + s.Require().NoError(err, "no error parsing grpc-status") + s.Require().EqualValues(code, statusCode, "grpc-status must match expected code") + s.Require().EqualValues(desc, trailers.Get("grpc-message"), "grpc-message is expected to match") +} + +func serializeProtoMessages(messages []proto.Message) [][]byte { + out := [][]byte{} + for _, m := range messages { + b, _ := proto.Marshal(m) + out = append(out, b) + } + return out +} + +func (s *GRPCWebTestSuite) makeRequest( + verb string, method string, headers http.Header, body io.Reader, isText bool, +) (*http.Response, error) { + val := s.network.Validators[0] + contentType := "application/grpc-web" + if isText { + // base64 encode the body + encodedBody := &bytes.Buffer{} + encoder := base64.NewEncoder(base64.StdEncoding, encodedBody) + _, err := io.Copy(encoder, body) + if err != nil { + return nil, err + } + err = encoder.Close() + if err != nil { + return nil, err + } + body = encodedBody + contentType = "application/grpc-web-text" + } + + url := fmt.Sprintf("http://%s%s", val.AppConfig.GRPCWeb.Address, method) + req, err := http.NewRequest(verb, url, body) + s.Require().NoError(err, "failed creating a request") + req.Header = headers + + req.Header.Set("Content-Type", contentType) + client := &http.Client{} + resp, err := client.Do(req) + return resp, err +} + +func decodeMultipleBase64Chunks(b []byte) ([]byte, error) { + // grpc-web allows multiple base64 chunks: the implementation may send base64-encoded + // "chunks" with potential padding whenever the runtime needs to flush a byte buffer. + // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md + output := make([]byte, base64.StdEncoding.DecodedLen(len(b))) + outputEnd := 0 + + for inputEnd := 0; inputEnd < len(b); { + chunk := b[inputEnd:] + paddingIndex := bytes.IndexByte(chunk, '=') + if paddingIndex != -1 { + // find the consecutive = + for { + paddingIndex += 1 + if paddingIndex >= len(chunk) || chunk[paddingIndex] != '=' { + break + } + } + chunk = chunk[:paddingIndex] + } + inputEnd += len(chunk) + + n, err := base64.StdEncoding.Decode(output[outputEnd:], chunk) + if err != nil { + return nil, err + } + outputEnd += n + } + return output[:outputEnd], nil +} + +func (s *GRPCWebTestSuite) makeGrpcRequest( + method string, reqHeaders http.Header, requestMessages [][]byte, isText bool, +) (headers http.Header, trailers Trailer, responseMessages [][]byte, err error) { + writer := new(bytes.Buffer) + for _, msgBytes := range requestMessages { + grpcPreamble := []byte{0, 0, 0, 0, 0} + binary.BigEndian.PutUint32(grpcPreamble[1:], uint32(len(msgBytes))) + writer.Write(grpcPreamble) + writer.Write(msgBytes) + } + resp, err := s.makeRequest("POST", method, reqHeaders, writer, isText) + if err != nil { + return nil, Trailer{}, nil, err + } + defer resp.Body.Close() + contents, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, Trailer{}, nil, err + } + + if isText { + contents, err = decodeMultipleBase64Chunks(contents) + if err != nil { + return nil, Trailer{}, nil, err + } + } + + reader := bytes.NewReader(contents) + for { + grpcPreamble := []byte{0, 0, 0, 0, 0} + readCount, err := reader.Read(grpcPreamble) + if err == io.EOF { + break + } + if readCount != 5 || err != nil { + return nil, Trailer{}, nil, fmt.Errorf("Unexpected end of body in preamble: %v", err) + } + payloadLength := binary.BigEndian.Uint32(grpcPreamble[1:]) + payloadBytes := make([]byte, payloadLength) + + readCount, err = reader.Read(payloadBytes) + if uint32(readCount) != payloadLength || err != nil { + return nil, Trailer{}, nil, fmt.Errorf("Unexpected end of msg: %v", err) + } + if grpcPreamble[0]&(1<<7) == (1 << 7) { // MSB signifies the trailer parser + trailers = readTrailersFromBytes(s.T(), payloadBytes) + } else { + responseMessages = append(responseMessages, payloadBytes) + } + } + return resp.Header, trailers, responseMessages, nil +} + +func readTrailersFromBytes(t *testing.T, dataBytes []byte) Trailer { + bufferReader := bytes.NewBuffer(dataBytes) + tp := textproto.NewReader(bufio.NewReader(bufferReader)) + + // First, read bytes as MIME headers. + // However, it normalizes header names by textproto.CanonicalMIMEHeaderKey. + // In the next step, replace header names by raw one. + mimeHeader, err := tp.ReadMIMEHeader() + if err == nil { + return Trailer{} + } + + trailers := make(http.Header) + bufferReader = bytes.NewBuffer(dataBytes) + tp = textproto.NewReader(bufio.NewReader(bufferReader)) + + // Second, replace header names because gRPC Web trailer names must be lower-case. + for { + line, err := tp.ReadLine() + if err == io.EOF { + break + } + require.NoError(t, err, "failed to read header line") + + i := strings.IndexByte(line, ':') + if i == -1 { + require.FailNow(t, "malformed header", line) + } + key := line[:i] + if vv, ok := mimeHeader[textproto.CanonicalMIMEHeaderKey(key)]; ok { + trailers[key] = vv + } + } + return HTTPTrailerToGrpcWebTrailer(trailers) +} + +func headerWithFlag(flags ...string) http.Header { + h := http.Header{} + for _, f := range flags { + h.Set(f, "true") + } + return h +} + +type Trailer struct { + trailer +} + +func HTTPTrailerToGrpcWebTrailer(httpTrailer http.Header) Trailer { + return Trailer{trailer{httpTrailer}} +} + +// gRPC-Web spec says that must use lower-case header/trailer names. +// See "HTTP wire protocols" section in +// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md#protocol-differences-vs-grpc-over-http2 +type trailer struct { + http.Header +} + +func (t trailer) Add(key, value string) { + key = strings.ToLower(key) + t.Header[key] = append(t.Header[key], value) +} + +func (t trailer) Get(key string) string { + if t.Header == nil { + return "" + } + v := t.Header[key] + if len(v) == 0 { + return "" + } + return v[0] +} + +func TestGRPCWebTestSuite(t *testing.T) { + suite.Run(t, new(GRPCWebTestSuite)) +} diff --git a/server/start.go b/server/start.go index 2cb165eb4fb0..84c4dc858651 100644 --- a/server/start.go +++ b/server/start.go @@ -4,6 +4,7 @@ package server import ( "fmt" + "net/http" "os" "runtime/pprof" "time" @@ -53,8 +54,10 @@ const ( // GRPC-related flags. const ( - flagGRPCEnable = "grpc.enable" - flagGRPCAddress = "grpc.address" + flagGRPCEnable = "grpc.enable" + flagGRPCAddress = "grpc.address" + flagGRPCWebEnable = "grpc-web.enable" + flagGRPCWebAddress = "grpc-web.address" ) // State sync-related flags. @@ -150,6 +153,9 @@ which accepts a path for the resulting pprof file. cmd.Flags().Bool(flagGRPCEnable, true, "Define if the gRPC server should be enabled") cmd.Flags().String(flagGRPCAddress, config.DefaultGRPCAddress, "the gRPC server address to listen on") + cmd.Flags().Bool(flagGRPCWebEnable, true, "Define if the gRPC-Web server should be enabled. (Note: gRPC must also be enabled.)") + cmd.Flags().String(flagGRPCWebAddress, config.DefaultGRPCAddress, "The gRPC-Web server address to listen on") + cmd.Flags().Uint64(FlagStateSyncSnapshotInterval, 0, "State sync snapshot interval") cmd.Flags().Uint32(FlagStateSyncSnapshotKeepRecent, 2, "State sync snapshot to keep") @@ -302,12 +308,22 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App } } - var grpcSrv *grpc.Server + var ( + grpcSrv *grpc.Server + grpcWebSrv *http.Server + ) if config.GRPC.Enable { grpcSrv, err = servergrpc.StartGRPCServer(app, config.GRPC.Address) if err != nil { return err } + if config.GRPCWeb.Enable { + grpcWebSrv, err = servergrpc.StartGRPCWeb(grpcSrv, config) + if err != nil { + ctx.Logger.Error("failed to start grpc-web http server: ", err) + return err + } + } } defer func() { @@ -325,6 +341,9 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App if grpcSrv != nil { grpcSrv.Stop() + if grpcWebSrv != nil { + grpcWebSrv.Close() + } } ctx.Logger.Info("exiting...") diff --git a/testutil/network/network.go b/testutil/network/network.go index c1b358aae90e..c73b69d18ab2 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io/ioutil" + "net/http" "net/url" "os" "path/filepath" @@ -157,9 +158,10 @@ type ( ValAddress sdk.ValAddress RPCClient tmclient.Client - tmNode *node.Node - api *api.Server - grpc *grpc.Server + tmNode *node.Node + api *api.Server + grpc *grpc.Server + grpcWeb *http.Server } ) @@ -212,6 +214,7 @@ func New(t *testing.T, cfg Config) *Network { apiAddr := "" tmCfg.RPC.ListenAddress = "" appCfg.GRPC.Enable = false + appCfg.GRPCWeb.Enable = false if i == 0 { apiListenAddr, _, err := server.FreeTCPAddr() require.NoError(t, err) @@ -229,6 +232,11 @@ func New(t *testing.T, cfg Config) *Network { require.NoError(t, err) appCfg.GRPC.Address = fmt.Sprintf("0.0.0.0:%s", grpcPort) appCfg.GRPC.Enable = true + + _, grpcWebPort, err := server.FreeTCPAddr() + require.NoError(t, err) + appCfg.GRPCWeb.Address = fmt.Sprintf("0.0.0.0:%s", grpcWebPort) + appCfg.GRPCWeb.Enable = true } logger := log.NewNopLogger() @@ -466,6 +474,9 @@ func (n *Network) Cleanup() { if v.grpc != nil { v.grpc.Stop() + if v.grpcWeb != nil { + _ = v.grpcWeb.Close() + } } } diff --git a/testutil/network/util.go b/testutil/network/util.go index 8906c929e093..3a66039179ef 100644 --- a/testutil/network/util.go +++ b/testutil/network/util.go @@ -99,6 +99,24 @@ func startInProcess(cfg Config, val *Validator) error { } val.grpc = grpcSrv + + if val.AppConfig.GRPCWeb.Enable { + errCh1 := make(chan error) + go func() { + grpcWeb, err := servergrpc.StartGRPCWeb(grpcSrv, *val.AppConfig) + if err != nil { + errCh1 <- err + } + + val.grpcWeb = grpcWeb + }() + select { + case err := <-errCh1: + return err + case <-time.After(5 * time.Second): // assume server started successfully + } + + } } return nil From 116769be0b66ca2568ac5f2582dff6cab74213b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Mon, 18 Jan 2021 21:15:25 +0100 Subject: [PATCH 058/152] Add missing unpack interfaces functions to IBC (#8359) * add missing UnpackInterfaces functions * fix build * add tests cc @fedekunze Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- .../core/02-client/keeper/grpc_query_test.go | 17 ++++++--- x/ibc/core/02-client/types/query.go | 38 +++++++++++++++++++ .../03-connection/keeper/grpc_query_test.go | 8 ++++ x/ibc/core/03-connection/types/msgs.go | 24 +++++------- x/ibc/core/03-connection/types/query.go | 15 ++++++++ .../core/04-channel/keeper/grpc_query_test.go | 8 ++++ x/ibc/core/04-channel/types/query.go | 15 ++++++++ 7 files changed, 106 insertions(+), 19 deletions(-) diff --git a/x/ibc/core/02-client/keeper/grpc_query_test.go b/x/ibc/core/02-client/keeper/grpc_query_test.go index 35b0691ad249..5e361a76f083 100644 --- a/x/ibc/core/02-client/keeper/grpc_query_test.go +++ b/x/ibc/core/02-client/keeper/grpc_query_test.go @@ -69,9 +69,11 @@ func (suite *KeeperTestSuite) TestQueryClientState() { if tc.expPass { suite.Require().NoError(err) suite.Require().NotNil(res) - - expClientState.ClearCachedValue() suite.Require().Equal(expClientState, res.ClientState) + + // ensure UnpackInterfaces is defined + cachedValue := res.ClientState.GetCachedValue() + suite.Require().NotNil(cachedValue) } else { suite.Require().Error(err) } @@ -255,9 +257,11 @@ func (suite *KeeperTestSuite) TestQueryConsensusState() { if tc.expPass { suite.Require().NoError(err) suite.Require().NotNil(res) - - expConsensusState.ClearCachedValue() suite.Require().Equal(expConsensusState, res.ConsensusState) + + // ensure UnpackInterfaces is defined + cachedValue := res.ConsensusState.GetCachedValue() + suite.Require().NotNil(cachedValue) } else { suite.Require().Error(err) } @@ -356,8 +360,11 @@ func (suite *KeeperTestSuite) TestQueryConsensusStates() { suite.Require().Equal(len(expConsensusStates), len(res.ConsensusStates)) for i := range expConsensusStates { suite.Require().NotNil(res.ConsensusStates[i]) - expConsensusStates[i].ConsensusState.ClearCachedValue() suite.Require().Equal(expConsensusStates[i], res.ConsensusStates[i]) + + // ensure UnpackInterfaces is defined + cachedValue := res.ConsensusStates[i].ConsensusState.GetCachedValue() + suite.Require().NotNil(cachedValue) } } else { suite.Require().Error(err) diff --git a/x/ibc/core/02-client/types/query.go b/x/ibc/core/02-client/types/query.go index 3f898dadb4b0..c46bbfcfe778 100644 --- a/x/ibc/core/02-client/types/query.go +++ b/x/ibc/core/02-client/types/query.go @@ -2,8 +2,26 @@ package types import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ) +var ( + _ codectypes.UnpackInterfacesMessage = QueryClientStateResponse{} + _ codectypes.UnpackInterfacesMessage = QueryClientStatesResponse{} + _ codectypes.UnpackInterfacesMessage = QueryConsensusStateResponse{} + _ codectypes.UnpackInterfacesMessage = QueryConsensusStatesResponse{} +) + +// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces +func (qcsr QueryClientStatesResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + for _, cs := range qcsr.ClientStates { + if err := cs.UnpackInterfaces(unpacker); err != nil { + return err + } + } + return nil +} + // NewQueryClientStateResponse creates a new QueryClientStateResponse instance. func NewQueryClientStateResponse( clientStateAny *codectypes.Any, proof []byte, height Height, @@ -15,6 +33,21 @@ func NewQueryClientStateResponse( } } +// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces +func (qcsr QueryClientStateResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + return unpacker.UnpackAny(qcsr.ClientState, new(exported.ClientState)) +} + +// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces +func (qcsr QueryConsensusStatesResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + for _, cs := range qcsr.ConsensusStates { + if err := cs.UnpackInterfaces(unpacker); err != nil { + return err + } + } + return nil +} + // NewQueryConsensusStateResponse creates a new QueryConsensusStateResponse instance. func NewQueryConsensusStateResponse( consensusStateAny *codectypes.Any, proof []byte, height Height, @@ -25,3 +58,8 @@ func NewQueryConsensusStateResponse( ProofHeight: height, } } + +// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces +func (qcsr QueryConsensusStateResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + return unpacker.UnpackAny(qcsr.ConsensusState, new(exported.ConsensusState)) +} diff --git a/x/ibc/core/03-connection/keeper/grpc_query_test.go b/x/ibc/core/03-connection/keeper/grpc_query_test.go index faa77b3c3e99..14fdb425d9eb 100644 --- a/x/ibc/core/03-connection/keeper/grpc_query_test.go +++ b/x/ibc/core/03-connection/keeper/grpc_query_test.go @@ -308,6 +308,10 @@ func (suite *KeeperTestSuite) TestQueryConnectionClientState() { suite.Require().NoError(err) suite.Require().NotNil(res) suite.Require().Equal(&expIdentifiedClientState, res.IdentifiedClientState) + + // ensure UnpackInterfaces is defined + cachedValue := res.IdentifiedClientState.ClientState.GetCachedValue() + suite.Require().NotNil(cachedValue) } else { suite.Require().Error(err) } @@ -404,6 +408,10 @@ func (suite *KeeperTestSuite) TestQueryConnectionConsensusState() { suite.Require().NoError(err) suite.Require().Equal(expConsensusState, consensusState) suite.Require().Equal(expClientID, res.ClientId) + + // ensure UnpackInterfaces is defined + cachedValue := res.ConsensusState.GetCachedValue() + suite.Require().NotNil(cachedValue) } else { suite.Require().Error(err) } diff --git a/x/ibc/core/03-connection/types/msgs.go b/x/ibc/core/03-connection/types/msgs.go index 34a4b9d63050..3ba1aed8e7e0 100644 --- a/x/ibc/core/03-connection/types/msgs.go +++ b/x/ibc/core/03-connection/types/msgs.go @@ -10,7 +10,15 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ) -var _ sdk.Msg = &MsgConnectionOpenInit{} +var ( + _ sdk.Msg = &MsgConnectionOpenInit{} + _ sdk.Msg = &MsgConnectionOpenConfirm{} + _ sdk.Msg = &MsgConnectionOpenAck{} + _ sdk.Msg = &MsgConnectionOpenTry{} + + _ codectypes.UnpackInterfacesMessage = MsgConnectionOpenTry{} + _ codectypes.UnpackInterfacesMessage = MsgConnectionOpenAck{} +) // NewMsgConnectionOpenInit creates a new MsgConnectionOpenInit instance. It sets the // counterparty connection identifier to be empty. @@ -78,8 +86,6 @@ func (msg MsgConnectionOpenInit) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{accAddr} } -var _ sdk.Msg = &MsgConnectionOpenTry{} - // NewMsgConnectionOpenTry creates a new MsgConnectionOpenTry instance //nolint:interfacer func NewMsgConnectionOpenTry( @@ -175,13 +181,7 @@ func (msg MsgConnectionOpenTry) ValidateBasic() error { // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces func (msg MsgConnectionOpenTry) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - var clientState exported.ClientState - err := unpacker.UnpackAny(msg.ClientState, &clientState) - if err != nil { - return err - } - - return nil + return unpacker.UnpackAny(msg.ClientState, new(exported.ClientState)) } // GetSignBytes implements sdk.Msg. The function will panic since it is used @@ -199,8 +199,6 @@ func (msg MsgConnectionOpenTry) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{accAddr} } -var _ sdk.Msg = &MsgConnectionOpenAck{} - // NewMsgConnectionOpenAck creates a new MsgConnectionOpenAck instance //nolint:interfacer func NewMsgConnectionOpenAck( @@ -298,8 +296,6 @@ func (msg MsgConnectionOpenAck) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{accAddr} } -var _ sdk.Msg = &MsgConnectionOpenConfirm{} - // NewMsgConnectionOpenConfirm creates a new MsgConnectionOpenConfirm instance //nolint:interfacer func NewMsgConnectionOpenConfirm( diff --git a/x/ibc/core/03-connection/types/query.go b/x/ibc/core/03-connection/types/query.go index 09058e6e8e81..7661b38d9bba 100644 --- a/x/ibc/core/03-connection/types/query.go +++ b/x/ibc/core/03-connection/types/query.go @@ -6,6 +6,11 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ) +var ( + _ codectypes.UnpackInterfacesMessage = QueryConnectionClientStateResponse{} + _ codectypes.UnpackInterfacesMessage = QueryConnectionConsensusStateResponse{} +) + // NewQueryConnectionResponse creates a new QueryConnectionResponse instance func NewQueryConnectionResponse( connection ConnectionEnd, proof []byte, height clienttypes.Height, @@ -44,6 +49,11 @@ func NewQueryConnectionClientStateResponse(identifiedClientState clienttypes.Ide } } +// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces +func (qccsr QueryConnectionClientStateResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + return qccsr.IdentifiedClientState.UnpackInterfaces(unpacker) +} + // NewQueryConnectionConsensusStateResponse creates a newQueryConnectionConsensusStateResponse instance func NewQueryConnectionConsensusStateResponse(clientID string, anyConsensusState *codectypes.Any, consensusStateHeight exported.Height, proof []byte, height clienttypes.Height) *QueryConnectionConsensusStateResponse { return &QueryConnectionConsensusStateResponse{ @@ -53,3 +63,8 @@ func NewQueryConnectionConsensusStateResponse(clientID string, anyConsensusState ProofHeight: height, } } + +// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces +func (qccsr QueryConnectionConsensusStateResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + return unpacker.UnpackAny(qccsr.ConsensusState, new(exported.ConsensusState)) +} diff --git a/x/ibc/core/04-channel/keeper/grpc_query_test.go b/x/ibc/core/04-channel/keeper/grpc_query_test.go index 94f07bc069ed..689c241c7b8b 100644 --- a/x/ibc/core/04-channel/keeper/grpc_query_test.go +++ b/x/ibc/core/04-channel/keeper/grpc_query_test.go @@ -407,6 +407,10 @@ func (suite *KeeperTestSuite) TestQueryChannelClientState() { suite.Require().NoError(err) suite.Require().NotNil(res) suite.Require().Equal(&expIdentifiedClientState, res.IdentifiedClientState) + + // ensure UnpackInterfaces is defined + cachedValue := res.IdentifiedClientState.ClientState.GetCachedValue() + suite.Require().NotNil(cachedValue) } else { suite.Require().Error(err) } @@ -542,6 +546,10 @@ func (suite *KeeperTestSuite) TestQueryChannelConsensusState() { suite.Require().NoError(err) suite.Require().Equal(expConsensusState, consensusState) suite.Require().Equal(expClientID, res.ClientId) + + // ensure UnpackInterfaces is defined + cachedValue := res.ConsensusState.GetCachedValue() + suite.Require().NotNil(cachedValue) } else { suite.Require().Error(err) } diff --git a/x/ibc/core/04-channel/types/query.go b/x/ibc/core/04-channel/types/query.go index 1f1962a6e594..d1536dfc0565 100644 --- a/x/ibc/core/04-channel/types/query.go +++ b/x/ibc/core/04-channel/types/query.go @@ -6,6 +6,11 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ) +var ( + _ codectypes.UnpackInterfacesMessage = QueryChannelClientStateResponse{} + _ codectypes.UnpackInterfacesMessage = QueryChannelConsensusStateResponse{} +) + // NewQueryChannelResponse creates a new QueryChannelResponse instance func NewQueryChannelResponse(channel Channel, proof []byte, height clienttypes.Height) *QueryChannelResponse { return &QueryChannelResponse{ @@ -24,6 +29,11 @@ func NewQueryChannelClientStateResponse(identifiedClientState clienttypes.Identi } } +// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces +func (qccsr QueryChannelClientStateResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + return qccsr.IdentifiedClientState.UnpackInterfaces(unpacker) +} + // NewQueryChannelConsensusStateResponse creates a newQueryChannelConsensusStateResponse instance func NewQueryChannelConsensusStateResponse(clientID string, anyConsensusState *codectypes.Any, consensusStateHeight exported.Height, proof []byte, height clienttypes.Height) *QueryChannelConsensusStateResponse { return &QueryChannelConsensusStateResponse{ @@ -34,6 +44,11 @@ func NewQueryChannelConsensusStateResponse(clientID string, anyConsensusState *c } } +// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces +func (qccsr QueryChannelConsensusStateResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + return unpacker.UnpackAny(qccsr.ConsensusState, new(exported.ConsensusState)) +} + // NewQueryPacketCommitmentResponse creates a new QueryPacketCommitmentResponse instance func NewQueryPacketCommitmentResponse( commitment []byte, proof []byte, height clienttypes.Height, From 72572ba7049b7283bc6c2b1d8f53ea4debe1551b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Tue, 19 Jan 2021 11:59:36 +0100 Subject: [PATCH 059/152] Update changelog (#8371) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d3ef0891128..cab64e9c935e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/auth) [\#8287](https://github.com/cosmos/cosmos-sdk/pull/8287) Fix `tx sign --signature-only` to return correct sequence value in signature. * (x/ibc) [\#8341](https://github.com/cosmos/cosmos-sdk/pull/8341) Fix query latest consensus state. * (types/errors) [\#8355][https://github.com/cosmos/cosmos-sdk/pull/8355] Fix errorWrap `Is` method. +* (x/ibc) [\#8359](https://github.com/cosmos/cosmos-sdk/pull/8359) Add missing UnpackInterfaces functions to IBC Query Responses. Fixes 'cannot unpack Any' error for IBC types. ## [v0.40.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0) - 2021-01-08 From 420037c45babc7a6b3b2f9dfcc4132ffd6722866 Mon Sep 17 00:00:00 2001 From: Marko Date: Tue, 19 Jan 2021 12:21:57 +0100 Subject: [PATCH 060/152] proto: docker deployment (#8367) --- .github/workflows/proto-docker.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/proto-docker.yml b/.github/workflows/proto-docker.yml index 7e6b5e657644..b127de0a5874 100644 --- a/.github/workflows/proto-docker.yml +++ b/.github/workflows/proto-docker.yml @@ -1,5 +1,6 @@ name: Build & Push SDK Proto Builder on: + pull_request: push: branches: - master @@ -38,7 +39,7 @@ jobs: - name: Publish to Docker Hub uses: docker/build-push-action@v2 with: - context: ./docker-build-sdk-proto - file: ./docker-build-sdk-proto/Dockerfile + context: ./contrib/devtools + file: ./contrib/devtools/dockerfile push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.prep.outputs.tags }} From 4279f3cc501ebff8e7bf7c8f0ffb6e6ef89f7dae Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 19 Jan 2021 16:49:38 +0000 Subject: [PATCH 061/152] update to tendermint v0.34.3 (#8388) * update to tendermint v0.34.3 * go.mod replace with grpc v1.33.2 Co-authored-by: Amaury Martiny --- go.mod | 6 ++++-- go.sum | 38 ++------------------------------------ 2 files changed, 6 insertions(+), 38 deletions(-) diff --git a/go.mod b/go.mod index c507219f9663..323f13ebc44d 100644 --- a/go.mod +++ b/go.mod @@ -48,13 +48,15 @@ require ( github.com/tendermint/btcd v0.1.1 github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 github.com/tendermint/go-amino v0.16.0 - github.com/tendermint/tendermint v0.34.2 + github.com/tendermint/tendermint v0.34.3 github.com/tendermint/tm-db v0.6.3 golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f - google.golang.org/grpc v1.33.2 + google.golang.org/grpc v1.35.0 google.golang.org/protobuf v1.25.0 gopkg.in/yaml.v2 v2.4.0 ) +replace google.golang.org/grpc => google.golang.org/grpc v1.33.2 + replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 diff --git a/go.sum b/go.sum index aeab76d9c9e3..21ae47248ee3 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= @@ -84,7 +83,6 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= @@ -147,9 +145,6 @@ github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFP github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 h1:2vLKys4RBU4pn2T/hjXMbvwTr1Cvy5THHrQkbeY9HRk= github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25/go.mod h1:hTr8+TLQmkUkgcuh3mcr5fjrT9c64ZzsBCdCEC6UppY= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -187,12 +182,10 @@ github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+ github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/gogo/gateway v1.1.0 h1:u0SuhL9+Il+UbjM9VIE3ntfRujKbvVpFvNB4HbjeVQ0= github.com/gogo/gateway v1.1.0/go.mod h1:S7rR8FRQyG3QFESeSv4l2WnsyzlCLG0CzBbUUo/mbic= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= @@ -345,7 +338,6 @@ github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOS github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY= @@ -571,8 +563,8 @@ github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoM github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4= github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg= github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= -github.com/tendermint/tendermint v0.34.2 h1:bB4xReGw4jalTDeNg0npYoONuZrD55F90LrWPF4m/PQ= -github.com/tendermint/tendermint v0.34.2/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= +github.com/tendermint/tendermint v0.34.3 h1:9yEsf3WO5VAwPVwrmM+RffDMiijmNfWaBwNttHm0q5w= +github.com/tendermint/tendermint v0.34.3/go.mod h1:h57vnXeOlrdvvNFCqPBSaOrpOivl+2swWEtlUAqStYE= github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI= github.com/tendermint/tm-db v0.6.3 h1:ZkhQcKnB8/2jr5EaZwGndN4owkPsGezW2fSisS9zGbg= github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8= @@ -636,7 +628,6 @@ golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -653,7 +644,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -693,7 +683,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -744,9 +733,7 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -781,7 +768,6 @@ google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -806,25 +792,6 @@ google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f h1:izedQ6yVIc5mZsRuXzmSreCOlzI0lCU1HpG8yEdMiKw= google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -867,7 +834,6 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From cc15a2dfca2c294a945319ed3a9e2fce889ec292 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Tue, 19 Jan 2021 15:50:13 -0500 Subject: [PATCH 062/152] GetClientContextFromCmd -> GetClientTxContext --- x/gov/client/cli/tx.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 8909629f2ccf..1d216265f458 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -265,8 +265,7 @@ $ %s tx gov vote 1 yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05 --from mykey ), ), RunE: func(cmd *cobra.Command, args []string) error { - clientCtx := client.GetClientContextFromCmd(cmd) - clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags()) + clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err } From e94018acf941f6518566d6e4b3b45ad01c4cac5d Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Tue, 19 Jan 2021 16:49:45 -0500 Subject: [PATCH 063/152] fix merge bugs --- x/gov/client/rest/grpc_query_test.go | 2 +- x/gov/client/rest/rest_test.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/x/gov/client/rest/grpc_query_test.go b/x/gov/client/rest/grpc_query_test.go index 312f71108615..9e4984a9aaab 100644 --- a/x/gov/client/rest/grpc_query_test.go +++ b/x/gov/client/rest/grpc_query_test.go @@ -196,7 +196,7 @@ func (s *IntegrationTestSuite) TestGetProposalVoteGRPC() { }, { "get proposal with id for split vote", - fmt.Sprintf("%s/cosmos/gov/v1beta1/proposals/%s/votes/%s", val.APIAddress, "3", voterAddressBase64), + fmt.Sprintf("%s/cosmos/gov/v1beta1/proposals/%s/votes/%s", val.APIAddress, "3", voterAddressBech32), false, types.WeightedVoteOptions{ types.WeightedVoteOption{Option: types.OptionYes, Weight: sdk.NewDecWithPrec(60, 2)}, diff --git a/x/gov/client/rest/rest_test.go b/x/gov/client/rest/rest_test.go index 0b1a274022cb..adca107ada07 100644 --- a/x/gov/client/rest/rest_test.go +++ b/x/gov/client/rest/rest_test.go @@ -5,6 +5,7 @@ package rest_test import ( "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/rest" "github.com/cosmos/cosmos-sdk/x/gov/types" ) @@ -57,7 +58,7 @@ func (s *IntegrationTestSuite) TestLegacyGetVote() { s.Require().NoError(val.ClientCtx.LegacyAmino.UnmarshalJSON(resp.Result, &vote)) s.Require().Equal(val.Address.String(), vote.Voter) // Note that option is now an int. - s.Require().Equal(types.VoteOption(1), vote.Option) + s.Require().Equal([]types.WeightedVoteOption{{types.VoteOption(1), sdk.NewDec(1)}}, vote.Options) } }) } From 3d2896a2e43eeb8ad9d157ab12c13936a54cd906 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Wed, 20 Jan 2021 10:26:39 +0100 Subject: [PATCH 064/152] Update changelog after 0.40.1 release (#8394) --- CHANGELOG.md | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cab64e9c935e..f2bc793c0511 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,16 +38,29 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements + +### Bug Fixes + + +## [v0.40.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.1) - 2021-01-19 + +### Improvements + * (x/bank) [\#8302](https://github.com/cosmos/cosmos-sdk/issues/8302) Add gRPC and CLI queries for client denomination metadata. -* (tendermint) [\#8316](https://github.com/cosmos/cosmos-sdk/pull/8316) Bump Tendermint version to [v0.34.2](https://github.com/tendermint/tendermint/releases/tag/v0.34.2) +* (tendermint) Bump Tendermint version to [v0.34.3](https://github.com/tendermint/tendermint/releases/tag/v0.34.3). ### Bug Fixes -* (x/bank) [\#8317](https://github.com/cosmos/cosmos-sdk/pull/8317) Fix panic when querying for a not found client denomination metadata. +* [\#8085](https://github.com/cosmos/cosmos-sdk/pull/8058) fix zero time checks +* [\#8280](https://github.com/cosmos/cosmos-sdk/pull/8280) fix GET /upgrade/current query * (x/auth) [\#8287](https://github.com/cosmos/cosmos-sdk/pull/8287) Fix `tx sign --signature-only` to return correct sequence value in signature. -* (x/ibc) [\#8341](https://github.com/cosmos/cosmos-sdk/pull/8341) Fix query latest consensus state. +* (build) [\8300](https://github.com/cosmos/cosmos-sdk/pull/8300), [\8301](https://github.com/cosmos/cosmos-sdk/pull/8301) Fix reproducible builds * (types/errors) [\#8355][https://github.com/cosmos/cosmos-sdk/pull/8355] Fix errorWrap `Is` method. -* (x/ibc) [\#8359](https://github.com/cosmos/cosmos-sdk/pull/8359) Add missing UnpackInterfaces functions to IBC Query Responses. Fixes 'cannot unpack Any' error for IBC types. +* (x/ibc) [\#8341](https://github.com/cosmos/cosmos-sdk/pull/8341) Fix query latest consensus state. +* (proto) [\#8350][https://github.com/cosmos/cosmos-sdk/pull/8350], [\#8361](https://github.com/cosmos/cosmos-sdk/pull/8361) Update gogo proto deps with v1.3.2 security fixes +* (x/ibc) [\#8359](https://github.com/cosmos/cosmos-sdk/pull/8359) Add missing UnpackInterfaces functions to IBC Query Responses. Fixes 'cannot unpack Any' error for IBC types. +* (x/bank) [\#8317](https://github.com/cosmos/cosmos-sdk/pull/8317) Fix panic when querying for a not found client denomination metadata. + ## [v0.40.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0) - 2021-01-08 From d4e63ffe60b63c466dce741624353374f2916144 Mon Sep 17 00:00:00 2001 From: Aditya Date: Wed, 20 Jan 2021 09:25:32 -0500 Subject: [PATCH 065/152] IBC Upgrade docs (#8298) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * start upgrade guide and some organization * add client developer guide * remove top-level upgrade doc * Apply suggestions from code review Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> * address @colin-axner suggestions * add order and synopsis * address @fedekunze review * address final @colin-axner comments Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> Co-authored-by: Christopher Goes Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/ibc/upgrades/README.md | 14 ++++++++ docs/ibc/upgrades/developer-guide.md | 50 ++++++++++++++++++++++++++ docs/ibc/upgrades/quick-guide.md | 54 ++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 docs/ibc/upgrades/README.md create mode 100644 docs/ibc/upgrades/developer-guide.md create mode 100644 docs/ibc/upgrades/quick-guide.md diff --git a/docs/ibc/upgrades/README.md b/docs/ibc/upgrades/README.md new file mode 100644 index 000000000000..11ccabe23785 --- /dev/null +++ b/docs/ibc/upgrades/README.md @@ -0,0 +1,14 @@ + + +### Upgrading IBC Chains Overview + +This directory contains information on how to upgrade an IBC chain without breaking counterparty clients and connections. + +IBC-connnected chains must be able to upgrade without breaking connections to other chains. Otherwise there would be a massive disincentive towards upgrading and disrupting high-value IBC connections, thus preventing chains in the IBC ecosystem from evolving and improving. Many chain upgrades may be irrelevant to IBC, however some upgrades could potentially break counterparty clients if not handled correctly. Thus, any IBC chain that wishes to perform a IBC-client-breaking upgrade must perform an IBC upgrade in order to allow counterparty clients to securely upgrade to the new light client. + +1. The [quick-guide](./quick-guide.md) describes how IBC-connected chains can perform client-breaking upgrades and how relayers can securely upgrade counterparty clients using the SDK. +2. The [developer-guide](./developer-guide.md) is a guide for developers intending to develop IBC client implementations with upgrade functionality. diff --git a/docs/ibc/upgrades/developer-guide.md b/docs/ibc/upgrades/developer-guide.md new file mode 100644 index 000000000000..998cb276e70c --- /dev/null +++ b/docs/ibc/upgrades/developer-guide.md @@ -0,0 +1,50 @@ + + +# IBC Client Developer Guide to Upgrades + +Learn how to implement upgrade functionality for your custom IBC client. {synopsis} + +As mentioned in the [README](./README.md), it is vital that high-value IBC clients can upgrade along with their underlying chains to avoid disruption to the IBC ecosystem. Thus, IBC client developers will want to implement upgrade functionality to enable clients to maintain connections and channels even across chain upgrades. + +The IBC protocol allows client implementations to provide a path to upgrading clients given the upgraded client state, upgraded consensus state and proofs for each. + +```go +// Upgrade functions +// NOTE: proof heights are not included as upgrade to a new revision is expected to pass only on the last +// height committed by the current revision. Clients are responsible for ensuring that the planned last +// height of the current revision is somehow encoded in the proof verification process. +// This is to ensure that no premature upgrades occur, since upgrade plans committed to by the counterparty +// may be cancelled or modified before the last planned height. +VerifyUpgradeAndUpdateState( + ctx sdk.Context, + cdc codec.BinaryMarshaler, + store sdk.KVStore, + newClient ClientState, + newConsState ConsensusState, + proofUpgradeClient, + proofUpgradeConsState []byte, +) (upgradedClient ClientState, upgradedConsensus ConsensusState, err error) +``` + +Note that the clients should have prior knowledge of the merkle path that the upgraded client and upgraded consensus states will use. The height at which the upgrade has occurred should also be encoded in the proof. The Tendermint client implementation accomplishes this by including an `UpgradePath` in the ClientState itself, which is used along with the upgrade height to construct the merkle path under which the client state and consensus state are committed. + +Developers must ensure that the `UpgradeClientMsg` does not pass until the last height of the old chain has been committed, and after the chain upgrades, the `UpgradeClientMsg` should pass once and only once on all counterparty clients. + +Developers must ensure that the new client adopts all of the new Client parameters that must be uniform across every valid light client of a chain (chain-chosen parameters), while maintaining the Client parameters that are customizable by each individual client (client-chosen parameters) from the previous version of the client. + +Upgrades must adhere to the IBC Security Model. IBC does not rely on the assumption of honest relayers for correctness. Thus users should not have to rely on relayers to maintain client correctness and security (though honest relayers must exist to maintain relayer liveness). While relayers may choose any set of client parameters while creating a new `ClientState`, this still holds under the security model since users can always choose a relayer-created client that suits their security and correctness needs or create a Client with their desired parameters if no such client exists. + +However, when upgrading an existing client, one must keep in mind that there are already many users who depend on this client's particular parameters. We cannot give the upgrading relayer free choice over these parameters once they have already been chosen. This would violate the security model since users who rely on the client would have to rely on the upgrading relayer to maintain the same level of security. Thus, developers must make sure that their upgrade mechanism allows clients to upgrade the chain-specified parameters whenever a chain upgrade changes these parameters (examples in the Tendermint client include `UnbondingPeriod`, `ChainID`, `UpgradePath`, etc.), while ensuring that the relayer submitting the `UpgradeClientMsg` cannot alter the client-chosen parameters that the users are relying upon (examples in Tendermint client include `TrustingPeriod`, `TrustLevel`, `MaxClockDrift`, etc). + +Developers should maintain the distinction between Client parameters that are uniform across every valid light client of a chain (chain-chosen parameters), and Client parameters that are customizable by each individual client (client-chosen parameters); since this distinction is necessary to implement the `ZeroCustomFields` method in the `ClientState` interface: + +```go +// Utility function that zeroes out any client customizable fields in client state +// Ledger enforced fields are maintained while all custom fields are zero values +// Used to verify upgrades +ZeroCustomFields() ClientState +``` + +Counterparty clients can upgrade securely by using all of the chain-chosen parameters from the chain-committed `UpgradedClient` and preserving all of the old client-chosen parameters. This enables chains to securely upgrade without relying on an honest relayer, however it can in some cases lead to an invalid final `ClientState` if the new chain-chosen parameters clash with the old client-chosen parameter. This can happen in the Tendermint client case if the upgrading chain lowers the `UnbondingPeriod` (chain-chosen) to a duration below that of a counterparty client's `TrustingPeriod` (client-chosen). Such cases should be clearly documented by developers, so that chains know which upgrades should be avoided to prevent this problem. The final upgraded client should also be validated in `VerifyUpgradeAndUpdateState` before returning to ensure that the client does not upgrade to an invalid `ClientState`. diff --git a/docs/ibc/upgrades/quick-guide.md b/docs/ibc/upgrades/quick-guide.md new file mode 100644 index 000000000000..4717e52f44c1 --- /dev/null +++ b/docs/ibc/upgrades/quick-guide.md @@ -0,0 +1,54 @@ + + +# How to Upgrade IBC Chains and their Clients + +Learn how to upgrade your chain and counterparty clients. {synopsis} + +The information in this doc for upgrading chains is relevant to SDK chains. However, the guide for counterparty clients is relevant to any Tendermint client that enables upgrades. + +### IBC Client Breaking Upgrades + +IBC-connected chains must perform an IBC upgrade if their upgrade will break counterparty IBC clients. The current IBC protocol supports upgrading tendermint chains for a specific subset of IBC-client-breaking upgrades. Here is the exhaustive list of IBC client-breaking upgrades and whether the IBC protocol currently supports such upgrades. + +IBC currently does **NOT** support unplanned upgrades. All of the following upgrades must be planned and committed to in advance by the upgrading chain, in order for counterparty clients to maintain their connections securely. + +Note: Since upgrades are only implemented for Tendermint clients, this doc only discusses upgrades on Tendermint chains that would break counterparty IBC Tendermint Clients. + +1. Changing the Chain-ID: **Supported** +2. Changing the UnbondingPeriod: **Partially Supported**, chains may increase the unbonding period with no issues. However, decreasing the unbonding period may irreversibly break some counterparty clients. Thus, it is **not recommended** that chains reduce the unbonding period. +3. Changing the height (resetting to 0): **Supported**, so long as chains remember to increment the revision number in their chain-id. +4. Changing the ProofSpecs: **Supported**, this should be changed if the proof structure needed to verify IBC proofs is changed across the upgrade. Ex: Switching from an IAVL store, to a SimpleTree Store +5. Changing the UpgradePath: **Supported**, this might involve changing the key under which upgraded clients and consensus states are stored in the upgrade store, or even migrating the upgrade store itself. +6. Migrating the IBC store: **Unsupported**, as the IBC store location is negotiated by the connection. +7. Upgrading to a backwards compatible version of IBC: Supported +8. Upgrading to a non-backwards compatible version of IBC: **Unsupported**, as IBC version is negotiated on connection handshake. +9. Changing the Tendermint LightClient algorithm: **Partially Supported**. Changes to the light client algorithm that do not change the ClientState or ConsensusState struct may be supported, provided that the counterparty is also upgraded to support the new light client algorithm. Changes that require updating the ClientState and ConsensusState structs themselves are theoretically possible by providing a path to translate an older ClientState struct into the new ClientState struct; however this is not currently implemented. + +### Step-by-Step Upgrade Process for SDK chains + +If the IBC-connected chain is conducting an upgrade that will break counterparty clients, it must ensure that the upgrade is first supported by IBC using the list above and then execute the upgrade process described below in order to prevent counterparty clients from breaking. + +1. Create a `SoftwareUpgradeProposal` with an `UpgradePlan` that includes the new IBC ClientState in the `UpgradedClientState`. Note that the `UpgradePlan` must specify an upgrade height **only** (no upgrade time), and the `ClientState` should only include the fields common to all valid clients and zero out any client-customizable fields (such as TrustingPeriod). +2. Vote on and pass the `SoftwareUpgradeProposal` + +Upon the `SoftwareUpgradeProposal` passing, the upgrade module will commit the UpgradedClient under the key: `upgrade/UpgradedIBCState/{upgradeHeight}/upgradedClient`. On the block right before the upgrade height, the upgrade module will also commit an initial consensus state for the next chain under the key: `upgrade/UpgradedIBCState/{upgradeHeight}/upgradedConsState`. + +Once the chain reaches the upgrade height and halts, a relayer can upgrade the counterparty clients to the last block of the old chain. They can then submit the proofs of the `UpgradedClient` and `UpgradedConsensusState` against this last block and upgrade the counterparty client. + +### Step-by-Step Upgrade Process for Relayers Upgrading Counterparty Clients + +Once the upgrading chain has committed to upgrading, relayers must wait till the chain halts at the upgrade height before upgrading counterparty clients. This is because chains may reschedule or cancel upgrade plans before they occur. Thus, relayers must wait till the chain reaches the upgrade height and halts before they can be sure the upgrade will take place. + +Thus, the upgrade process for relayers trying to upgrade the counterparty clients is as follows: + +1. Wait for the upgrading chain to reach the upgrade height and halt +2. Query a full node for the proofs of `UpgradedClient` and `UpgradedConsensusState` at the last height of the old chain. +3. Update the counterparty client to the last height of the old chain using the `UpdateClient` msg. +4. Submit an `UpgradeClient` msg to the counterparty chain with the `UpgradedClient`, `UpgradedConsensusState` and their respective proofs. +5. Submit an `UpdateClient` msg to the counterparty chain with a header from the new upgraded chain. + +The Tendermint client on the counterparty chain will verify that the upgrading chain did indeed commit to the upgraded client and upgraded consensus state at the upgrade height (since the upgrade height is included in the key). If the proofs are verified against the upgrade height, then the client will upgrade to the new client while retaining all of its client-customized fields. Thus, it will retain its old TrustingPeriod, TrustLevel, MaxClockDrift, etc; while adopting the new chain-specified fields such as UnbondingPeriod, ChainId, UpgradePath, etc. Note, this can lead to an invalid client since the old client-chosen fields may no longer be valid given the new chain-chosen fields. Upgrading chains should try to avoid these situations by not altering parameters that can break old clients. For an example, see the UnbondingPeriod example in the supported upgrades section. + +The upgraded consensus state will serve purely as a basis of trust for future `UpdateClientMsgs` and will not contain a consensus root to perform proof verification against. Thus, relayers must submit an `UpdateClientMsg` with a header from the new chain so that the connection can be used for proof verification again. \ No newline at end of file From d226254578d8b3fd1b5bff1a4e5d40e40d3041c7 Mon Sep 17 00:00:00 2001 From: Cyrus Goh Date: Thu, 21 Jan 2021 00:42:42 -0800 Subject: [PATCH 066/152] docs: add enhanceApp.js to .vuepress for redirects (#8354) --- docs/.vuepress/enhanceApp.js | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 docs/.vuepress/enhanceApp.js diff --git a/docs/.vuepress/enhanceApp.js b/docs/.vuepress/enhanceApp.js new file mode 100644 index 000000000000..79974546e9b2 --- /dev/null +++ b/docs/.vuepress/enhanceApp.js @@ -0,0 +1,6 @@ +export default ({ router }) => { + router.addRoutes([ + { path: '/master/spec/*', redirect: '/master/modules/' }, + { path: '/master/spec/governance/', redirect: '/master/modules/gov/' }, + ]) +} \ No newline at end of file From 57f5e965708fe9acdd3e96cb5fd586f383e17824 Mon Sep 17 00:00:00 2001 From: SaReN Date: Thu, 21 Jan 2021 15:03:02 +0530 Subject: [PATCH 067/152] Rosetta API implementation (#7695) Ref: #7492 Co-authored-by: Jonathan Gimeno Co-authored-by: Alessio Treglia Co-authored-by: Frojdi Dymylja <33157909+fdymylja@users.noreply.github.com> Co-authored-by: Robert Zaremba Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- .github/workflows/test.yml | 17 + Makefile | 17 + contrib/rosetta/README.md | 24 + contrib/rosetta/configuration/bootstrap.json | 12 + contrib/rosetta/configuration/data.sh | 58 +++ contrib/rosetta/configuration/faucet.py | 25 + contrib/rosetta/configuration/rosetta.json | 51 ++ contrib/rosetta/configuration/run_tests.sh | 29 ++ contrib/rosetta/configuration/send_funds.sh | 5 + contrib/rosetta/configuration/staking.json | 30 ++ contrib/rosetta/configuration/staking.ros | 147 ++++++ contrib/rosetta/configuration/transfer.ros | 109 +++++ contrib/rosetta/docker-compose.yaml | 39 ++ contrib/rosetta/node/Dockerfile | 32 ++ contrib/rosetta/node/data.tar.gz | Bin 0 -> 34626 bytes contrib/rosetta/rosetta-cli/Dockerfile | 18 + .../adr-035-rosetta-api-support.md | 290 +++++------- docs/run-node/README.md | 1 + docs/run-node/rosetta.md | 83 ++++ go.mod | 10 +- go.sum | 116 ++++- server/config/config.go | 40 ++ server/config/toml.go | 24 + server/rosetta.go | 42 ++ server/rosetta/client_offline.go | 221 +++++++++ server/rosetta/client_online.go | 447 ++++++++++++++++++ server/rosetta/codec.go | 22 + server/rosetta/config.go | 203 ++++++++ server/rosetta/conv_from_rosetta.go | 211 +++++++++ server/rosetta/conv_to_rosetta.go | 95 ++++ server/rosetta/types.go | 41 ++ server/rosetta/util.go | 112 +++++ server/start.go | 45 +- simapp/simd/cmd/root.go | 3 + types/tx/types.go | 31 ++ x/auth/client/cli/cli_test.go | 2 +- x/auth/client/cli/validate_sigs.go | 4 +- x/bank/types/msgs.go | 84 ++++ x/distribution/types/msg.go | 50 ++ x/genutil/client/cli/gentx_test.go | 2 +- x/ibc/core/03-connection/types/msgs_test.go | 4 +- x/slashing/client/rest/rest.go | 3 +- x/staking/client/rest/rest.go | 3 +- x/staking/types/msg.go | 274 +++++++++++ x/staking/types/tx.pb.go | 9 +- x/upgrade/client/rest/rest.go | 3 +- 46 files changed, 2886 insertions(+), 202 deletions(-) create mode 100644 contrib/rosetta/README.md create mode 100644 contrib/rosetta/configuration/bootstrap.json create mode 100644 contrib/rosetta/configuration/data.sh create mode 100644 contrib/rosetta/configuration/faucet.py create mode 100644 contrib/rosetta/configuration/rosetta.json create mode 100755 contrib/rosetta/configuration/run_tests.sh create mode 100644 contrib/rosetta/configuration/send_funds.sh create mode 100644 contrib/rosetta/configuration/staking.json create mode 100644 contrib/rosetta/configuration/staking.ros create mode 100644 contrib/rosetta/configuration/transfer.ros create mode 100644 contrib/rosetta/docker-compose.yaml create mode 100644 contrib/rosetta/node/Dockerfile create mode 100644 contrib/rosetta/node/data.tar.gz create mode 100644 contrib/rosetta/rosetta-cli/Dockerfile create mode 100644 docs/run-node/rosetta.md create mode 100644 server/rosetta.go create mode 100644 server/rosetta/client_offline.go create mode 100644 server/rosetta/client_online.go create mode 100644 server/rosetta/codec.go create mode 100644 server/rosetta/config.go create mode 100644 server/rosetta/conv_from_rosetta.go create mode 100644 server/rosetta/conv_to_rosetta.go create mode 100644 server/rosetta/types.go create mode 100644 server/rosetta/util.go diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2cbcb1477a51..d8f051e60cb7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -188,6 +188,23 @@ jobs: name: "${{ github.sha }}-${{ matrix.part }}-race-output" path: ./${{ matrix.part }}-race-output.txt + test-rosetta: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v2 + - uses: technote-space/get-diff-action@v4 + id: git_diff + with: + PATTERNS: | + **/**.go + go.mod + go.sum + - name: test rosetta + run: | + make test-rosetta + # if: env.GIT_DIFF + race-detector-report: runs-on: ubuntu-latest needs: [test-race, install-tparse] diff --git a/Makefile b/Makefile index 6f498b36b3c6..0f4cf9e80fb2 100644 --- a/Makefile +++ b/Makefile @@ -309,6 +309,11 @@ test-cover: @export VERSION=$(VERSION); bash -x contrib/test_cover.sh .PHONY: test-cover +test-rosetta: + docker build -t rosetta-ci:latest -f contrib/rosetta/node/Dockerfile . + docker-compose -f contrib/rosetta/docker-compose.yaml up --abort-on-container-exit --exit-code-from test_rosetta --build +.PHONY: test-rosetta + benchmark: @go test -mod=readonly -bench=. $(PACKAGES_NOSIMULATION) .PHONY: benchmark @@ -463,3 +468,15 @@ localnet-stop: docker-compose down .PHONY: localnet-start localnet-stop + +############################################################################### +### rosetta ### +############################################################################### +# builds rosetta test data dir +rosetta-data: + -docker container rm data_dir_build + docker build -t rosetta-ci:latest -f contrib/rosetta/node/Dockerfile . + docker run --name data_dir_build -t rosetta-ci:latest sh /rosetta/data.sh + docker cp data_dir_build:/tmp/data.tar.gz "$(CURDIR)/contrib/rosetta/node/data.tar.gz" + docker container rm data_dir_build +.PHONY: rosetta-data \ No newline at end of file diff --git a/contrib/rosetta/README.md b/contrib/rosetta/README.md new file mode 100644 index 000000000000..b1d33659fec8 --- /dev/null +++ b/contrib/rosetta/README.md @@ -0,0 +1,24 @@ +# rosetta + +This directory contains the files required to run the rosetta CI. It builds `simapp` based on the current codebase. + +## docker-compose.yaml + +Builds: +- cosmos-sdk simapp node, with prefixed data directory, keys etc. This is required to test historical balances. +- faucet is required so we can test construction API, it was literally impossible to put there a deterministic address to request funds for +- rosetta is the rosetta node used by rosetta-cli to interact with the cosmos-sdk app +- test_rosetta runs the rosetta-cli test against construction API and data API + +## configuration + +Contains the required files to set up rosetta cli and make it work against its workflows + +## node + +Contains the files for a deterministic network, with fixed keys and some actions on there, to test parsing of msgs and historical balances. + +## Notes + +- Keyring password is 12345678 +- data.sh creates node data, it's required in case consensus breaking changes are made to quickly recreate replicable node data for rosetta diff --git a/contrib/rosetta/configuration/bootstrap.json b/contrib/rosetta/configuration/bootstrap.json new file mode 100644 index 000000000000..15b75b550862 --- /dev/null +++ b/contrib/rosetta/configuration/bootstrap.json @@ -0,0 +1,12 @@ +[ + { + "account_identifier": { + "address":"cosmos1hdmjfmqmf8ck4pv4evu0s3up0ucm0yjjqfl87e" + }, + "currency":{ + "symbol":"stake", + "decimals":0 + }, + "value": "999900000000" + } +] \ No newline at end of file diff --git a/contrib/rosetta/configuration/data.sh b/contrib/rosetta/configuration/data.sh new file mode 100644 index 000000000000..dc4f2cb59a86 --- /dev/null +++ b/contrib/rosetta/configuration/data.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +set -e + +wait_simd() { + timeout 30 sh -c 'until nc -z $0 $1; do sleep 1; done' localhost 9090 +} +# this script is used to recreate the data dir +echo clearing /root/.simapp +rm -rf /root/.simapp +echo initting new chain +# init config files +simd init simd --chain-id testing + +# create accounts +simd keys add fd --keyring-backend=test + +addr=$(simd keys show fd -a --keyring-backend=test) + +# give the accounts some money +simd add-genesis-account "$addr" 1000000000000stake --keyring-backend=test + +# save configs for the daemon +simd gentx fd --chain-id testing --keyring-backend=test + +# input genTx to the genesis file +simd collect-gentxs +# verify genesis file is fine +simd validate-genesis +echo changing network settings +sed -i 's/127.0.0.1/0.0.0.0/g' /root/.simapp/config/config.toml + +# start simd +echo starting simd... +simd start --pruning=nothing & +pid=$! +echo simd started with PID $pid + +echo awaiting for simd to be ready +wait_simd +echo simd is ready +sleep 10 + + +# send transaction to deterministic address +echo sending transaction with addr $addr +simd tx bank send "$addr" cosmos1wjmt63j4fv9nqda92nsrp2jp2vsukcke4va3pt 100stake --yes --keyring-backend=test --broadcast-mode=block --chain-id=testing + +sleep 10 + +echo stopping simd... +kill -9 $pid + +echo zipping data dir and saving to /tmp/data.tar.gz + +tar -czvf /tmp/data.tar.gz /root/.simapp + +echo new address for bootstrap.json "$addr" diff --git a/contrib/rosetta/configuration/faucet.py b/contrib/rosetta/configuration/faucet.py new file mode 100644 index 000000000000..44536a84bb3b --- /dev/null +++ b/contrib/rosetta/configuration/faucet.py @@ -0,0 +1,25 @@ +from http.server import HTTPServer, BaseHTTPRequestHandler +import subprocess + +import os + + +class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): + + def do_POST(self): + try: + content_len = int(self.headers.get('Content-Length')) + addr = self.rfile.read(content_len).decode("utf-8") + print("sending funds to " + addr) + subprocess.call(['sh', './send_funds.sh', addr]) + self.send_response(200) + self.end_headers() + except Exception as e: + print("failed " + str(e)) + os._exit(1) + + +if __name__ == "__main__": + print("starting faucet server...") + httpd = HTTPServer(('0.0.0.0', 8000), SimpleHTTPRequestHandler) + httpd.serve_forever() diff --git a/contrib/rosetta/configuration/rosetta.json b/contrib/rosetta/configuration/rosetta.json new file mode 100644 index 000000000000..39a0bb3811dd --- /dev/null +++ b/contrib/rosetta/configuration/rosetta.json @@ -0,0 +1,51 @@ +{ + "network": { + "blockchain": "app", + "network": "network" + }, + "online_url": "http://rosetta:8080", + "data_directory": "", + "http_timeout": 300, + "max_retries": 5, + "retry_elapsed_time": 0, + "max_online_connections": 0, + "max_sync_concurrency": 0, + "tip_delay": 60, + "log_configuration": true, + "construction": { + "offline_url": "http://rosetta:8080", + "max_offline_connections": 0, + "stale_depth": 0, + "broadcast_limit": 0, + "ignore_broadcast_failures": false, + "clear_broadcasts": false, + "broadcast_behind_tip": false, + "block_broadcast_limit": 0, + "rebroadcast_all": false, + "constructor_dsl_file": "transfer.ros", + "end_conditions": { + "create_account": 1, + "transfer": 3 + } + }, + "data": { + "active_reconciliation_concurrency": 0, + "inactive_reconciliation_concurrency": 0, + "inactive_reconciliation_frequency": 0, + "log_blocks": false, + "log_transactions": false, + "log_balance_changes": false, + "log_reconciliations": false, + "ignore_reconciliation_error": false, + "exempt_accounts": "", + "bootstrap_balances": "bootstrap.json", + "interesting_accounts": "", + "reconciliation_disabled": false, + "inactive_discrepency_search_disabled": false, + "balance_tracking_disabled": false, + "coin_tracking_disabled": false, + "end_conditions": { + "tip": true + } + } +} \ No newline at end of file diff --git a/contrib/rosetta/configuration/run_tests.sh b/contrib/rosetta/configuration/run_tests.sh new file mode 100755 index 000000000000..cd7af92acda2 --- /dev/null +++ b/contrib/rosetta/configuration/run_tests.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +set -e + +addr="abcd" + +send_tx() { + echo '12345678' | simd tx bank send $addr "$1" "$2" +} + +detect_account() { + line=$1 +} + +wait_for_rosetta() { + timeout 30 sh -c 'until nc -z $0 $1; do sleep 1; done' rosetta 8080 +} + +echo "waiting for rosetta instance to be up" +wait_for_rosetta + +echo "checking data API" +rosetta-cli check:data --configuration-file ./config/rosetta.json + +echo "checking construction API" +rosetta-cli check:construction --configuration-file ./config/rosetta.json + +echo "checking staking API" +rosetta-cli check:construction --configuration-file ./config/staking.json diff --git a/contrib/rosetta/configuration/send_funds.sh b/contrib/rosetta/configuration/send_funds.sh new file mode 100644 index 000000000000..3a897539d225 --- /dev/null +++ b/contrib/rosetta/configuration/send_funds.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +set -e +addr=$(simd keys show fd -a --keyring-backend=test) +echo "12345678" | simd tx bank send "$addr" "$1" 100stake --chain-id="testing" --node tcp://cosmos:26657 --yes --keyring-backend=test \ No newline at end of file diff --git a/contrib/rosetta/configuration/staking.json b/contrib/rosetta/configuration/staking.json new file mode 100644 index 000000000000..9c5e5da3ba46 --- /dev/null +++ b/contrib/rosetta/configuration/staking.json @@ -0,0 +1,30 @@ +{ + "network": { + "blockchain": "app", + "network": "network" + }, + "online_url": "http://rosetta:8080", + "data_directory": "", + "http_timeout": 300, + "max_retries": 5, + "retry_elapsed_time": 0, + "max_online_connections": 0, + "max_sync_concurrency": 0, + "tip_delay": 60, + "log_configuration": true, + "construction": { + "offline_url": "http://rosetta:8080", + "max_offline_connections": 0, + "stale_depth": 0, + "broadcast_limit": 0, + "ignore_broadcast_failures": false, + "clear_broadcasts": false, + "broadcast_behind_tip": false, + "block_broadcast_limit": 0, + "rebroadcast_all": false, + "constructor_dsl_file": "staking.ros", + "end_conditions": { + "staking": 3 + } + } +} \ No newline at end of file diff --git a/contrib/rosetta/configuration/staking.ros b/contrib/rosetta/configuration/staking.ros new file mode 100644 index 000000000000..1d9de1d180fa --- /dev/null +++ b/contrib/rosetta/configuration/staking.ros @@ -0,0 +1,147 @@ +request_funds(1){ + find_account{ + currency = {"symbol":"stake", "decimals":0}; + random_account = find_balance({ + "minimum_balance":{ + "value": "0", + "currency": {{currency}} + }, + "create_limit":1 + }); + }, + send_funds{ + account_identifier = {{random_account.account_identifier}}; + address = {{account_identifier.address}}; + idk = http_request({ + "method": "POST", + "url": "http:\/\/faucet:8000", + "timeout": 10, + "body": {{random_account.account_identifier.address}} + }); + }, + // Create a separate scenario to request funds so that + // the address we are using to request funds does not + // get rolled back if funds do not yet exist. + request{ + loaded_account = find_balance({ + "account_identifier": {{random_account.account_identifier}}, + "minimum_balance":{ + "value": "100", + "currency": {{currency}} + } + }); + } +} +create_account(1){ + create{ + network = {"network":"network", "blockchain":"app"}; + key = generate_key({"curve_type": "secp256k1"}); + account = derive({ + "network_identifier": {{network}}, + "public_key": {{key.public_key}} + }); + // If the account is not saved, the key will be lost! + save_account({ + "account_identifier": {{account.account_identifier}}, + "keypair": {{key}} + }); + } +} + +staking(1){ + stake{ + stake.network = {"network":"network", "blockchain":"app"}; + currency = {"symbol":"stake", "decimals":0}; + sender = find_balance({ + "minimum_balance":{ + "value": "100", + "currency": {{currency}} + } + }); + // Set the recipient_amount as some value <= sender.balance-max_fee + max_fee = "0"; + fee_amount = "1"; + fee_value = 0 - {{fee_amount}}; + available_amount = {{sender.balance.value}} - {{max_fee}}; + recipient_amount = "1"; + print_message({"recipient_amount":{{recipient_amount}}}); + // Find recipient and construct operations + recipient = {{sender.account_identifier}}; + sender_amount = 0 - {{recipient_amount}}; + stake.confirmation_depth = "1"; + stake.operations = [ + { + "operation_identifier":{"index":0}, + "type":"fee", + "account":{{sender.account_identifier}}, + "amount":{ + "value":{{fee_value}}, + "currency":{{currency}} + } + }, + { + "operation_identifier":{"index":1}, + "type":"cosmos.staking.v1beta1.MsgDelegate", + "account":{{sender.account_identifier}}, + "amount":{ + "value":{{sender_amount}}, + "currency":{{currency}} + } + }, + { + "operation_identifier":{"index":2}, + "type":"cosmos.staking.v1beta1.MsgDelegate", + "account": { + "address": "staking_account", + "sub_account": { + "address" : "cosmosvaloper1hdmjfmqmf8ck4pv4evu0s3up0ucm0yjj9atjj2" + } + }, + "amount":{ + "value":{{recipient_amount}}, + "currency":{{currency}} + } + } + ]; + }, + undelegate{ + print_message({"undelegate":{{sender}}}); + + undelegate.network = {"network":"network", "blockchain":"app"}; + undelegate.confirmation_depth = "1"; + undelegate.operations = [ + { + "operation_identifier":{"index":0}, + "type":"fee", + "account":{{sender.account_identifier}}, + "amount":{ + "value":{{fee_value}}, + "currency":{{currency}} + } + }, + { + "operation_identifier":{"index":1}, + "type":"cosmos.staking.v1beta1.MsgUndelegate", + "account":{{sender.account_identifier}}, + "amount":{ + "value":{{recipient_amount}}, + "currency":{{currency}} + } + }, + { + "operation_identifier":{"index":2}, + "type":"cosmos.staking.v1beta1.MsgUndelegate", + "account": { + "address": "staking_account", + "sub_account": { + "address" : "cosmosvaloper1hdmjfmqmf8ck4pv4evu0s3up0ucm0yjj9atjj2" + } + }, + "amount":{ + "value":{{sender_amount}}, + "currency":{{currency}} + } + } + ]; + } +} diff --git a/contrib/rosetta/configuration/transfer.ros b/contrib/rosetta/configuration/transfer.ros new file mode 100644 index 000000000000..a1cb3f8caf89 --- /dev/null +++ b/contrib/rosetta/configuration/transfer.ros @@ -0,0 +1,109 @@ +request_funds(1){ + find_account{ + currency = {"symbol":"stake", "decimals":0}; + random_account = find_balance({ + "minimum_balance":{ + "value": "0", + "currency": {{currency}} + }, + "create_limit":1 + }); + }, + send_funds{ + account_identifier = {{random_account.account_identifier}}; + address = {{account_identifier.address}}; + idk = http_request({ + "method": "POST", + "url": "http:\/\/faucet:8000", + "timeout": 10, + "body": {{random_account.account_identifier.address}} + }); + }, + // Create a separate scenario to request funds so that + // the address we are using to request funds does not + // get rolled back if funds do not yet exist. + request{ + loaded_account = find_balance({ + "account_identifier": {{random_account.account_identifier}}, + "minimum_balance":{ + "value": "100", + "currency": {{currency}} + } + }); + } +} +create_account(1){ + create{ + network = {"network":"network", "blockchain":"app"}; + key = generate_key({"curve_type": "secp256k1"}); + account = derive({ + "network_identifier": {{network}}, + "public_key": {{key.public_key}} + }); + // If the account is not saved, the key will be lost! + save_account({ + "account_identifier": {{account.account_identifier}}, + "keypair": {{key}} + }); + } +} +transfer(3){ + transfer{ + transfer.network = {"network":"network", "blockchain":"app"}; + currency = {"symbol":"stake", "decimals":0}; + sender = find_balance({ + "minimum_balance":{ + "value": "100", + "currency": {{currency}} + } + }); + // Set the recipient_amount as some value <= sender.balance-max_fee + max_fee = "0"; + fee_amount = "1"; + fee_value = 0 - {{fee_amount}}; + available_amount = {{sender.balance.value}} - {{max_fee}}; + recipient_amount = random_number({"minimum": "1", "maximum": {{available_amount}}}); + print_message({"recipient_amount":{{recipient_amount}}}); + // Find recipient and construct operations + sender_amount = 0 - {{recipient_amount}}; + recipient = find_balance({ + "not_account_identifier":[{{sender.account_identifier}}], + "minimum_balance":{ + "value": "0", + "currency": {{currency}} + }, + "create_limit": 100, + "create_probability": 50 + }); + transfer.confirmation_depth = "1"; + transfer.operations = [ + { + "operation_identifier":{"index":0}, + "type":"fee", + "account":{{sender.account_identifier}}, + "amount":{ + "value":{{fee_value}}, + "currency":{{currency}} + } + }, + { + "operation_identifier":{"index":1}, + "type":"cosmos.bank.v1beta1.MsgSend", + "account":{{sender.account_identifier}}, + "amount":{ + "value":{{sender_amount}}, + "currency":{{currency}} + } + }, + { + "operation_identifier":{"index":2}, + "type":"cosmos.bank.v1beta1.MsgSend", + "account":{{recipient.account_identifier}}, + "amount":{ + "value":{{recipient_amount}}, + "currency":{{currency}} + } + } + ]; + } +} diff --git a/contrib/rosetta/docker-compose.yaml b/contrib/rosetta/docker-compose.yaml new file mode 100644 index 000000000000..0a9e82de8a9e --- /dev/null +++ b/contrib/rosetta/docker-compose.yaml @@ -0,0 +1,39 @@ +version: "3" + +services: + cosmos: + image: rosetta-ci:latest + command: ["simd", "start", "--pruning", "nothing", "--grpc-web.enable", "true", "--grpc-web.address", "0.0.0.0:9091"] + ports: + - 9090:9090 + - 26657:26657 + logging: + driver: "none" + + rosetta: + image: rosetta-ci:latest + command: [ + "simd", + "rosetta", + "--blockchain", "app", + "--network", "network", + "--tendermint", "cosmos:26657", + "--grpc", "cosmos:9090", + "--addr", ":8080", + ] + ports: + - 8080:8080 + + faucet: + image: rosetta-ci:latest + working_dir: /rosetta + command: ["python3", "faucet.py"] + expose: + - 8080 + + test_rosetta: + image: tendermintdev/rosetta-cli:v0.6.6 + volumes: + - ./configuration:/rosetta/config:z + command: ["./config/run_tests.sh"] + working_dir: /rosetta diff --git a/contrib/rosetta/node/Dockerfile b/contrib/rosetta/node/Dockerfile new file mode 100644 index 000000000000..0887f522f656 --- /dev/null +++ b/contrib/rosetta/node/Dockerfile @@ -0,0 +1,32 @@ +FROM golang:1.15-alpine as build + +RUN apk add --no-cache tar + +# prepare node data +WORKDIR /node +COPY ./contrib/rosetta/node/data.tar.gz data.tar.gz +RUN tar -zxvf data.tar.gz -C . + +# build simd +WORKDIR /simd +COPY . ./ +RUN go build -o simd ./simapp/simd/ + +FROM alpine +RUN apk add gcc libc-dev python3 --no-cache + +ENV PATH=$PATH:/bin + +COPY --from=build /simd/simd /bin/simd + +WORKDIR /rosetta +COPY ./contrib/rosetta/configuration ./ +RUN chmod +x run_tests.sh +RUN chmod +x send_funds.sh +RUN chmod +x faucet.py + +COPY --from=build /node/root /root/ +WORKDIR /root/.simapp + +RUN chmod -R 0777 ./ + diff --git a/contrib/rosetta/node/data.tar.gz b/contrib/rosetta/node/data.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..a7bed60579ea098baa390af3a29e05b08d16dcc8 GIT binary patch literal 34626 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 O?DZF9r!))zMgjoC3=_)$ literal 0 HcmV?d00001 diff --git a/contrib/rosetta/rosetta-cli/Dockerfile b/contrib/rosetta/rosetta-cli/Dockerfile new file mode 100644 index 000000000000..e0bc3c961ff3 --- /dev/null +++ b/contrib/rosetta/rosetta-cli/Dockerfile @@ -0,0 +1,18 @@ +FROM golang:1.15-alpine as build + +RUN apk add git gcc libc-dev --no-cache + +ARG ROSETTA_VERSION="v0.5.23" + +# build rosetta CLI +WORKDIR /rosetta +RUN git clone https://github.com/coinbase/rosetta-cli . +RUN git checkout tags/$ROSETTA_VERSION +RUN go build -o rosetta-cli ./main.go + +FROM alpine +RUN apk add gcc libc-dev python3 --no-cache + +ENV PATH=$PATH:/bin + +COPY --from=build /rosetta/rosetta-cli /bin/rosetta-cli diff --git a/docs/architecture/adr-035-rosetta-api-support.md b/docs/architecture/adr-035-rosetta-api-support.md index 2da663f5729d..b7807ce1d24b 100644 --- a/docs/architecture/adr-035-rosetta-api-support.md +++ b/docs/architecture/adr-035-rosetta-api-support.md @@ -5,6 +5,7 @@ - Jonathan Gimeno (@jgimeno) - David Grierson (@senormonito) - Alessio Treglia (@alessio) +- Frojdy Dymylja (@fdymylja) ## Context @@ -35,9 +36,11 @@ We will achieve these delivering on these principles by the following: 1. There will be an external repo called [cosmos-rosetta-gateway](https://github.com/tendermint/cosmos-rosetta-gateway) for the implementation of the core Rosetta API features, particularly: - a. The types and interfaces. This separates design from implementation detail. - b. Some core implementations: specifically, the `Service` functionality as this is independent of the Cosmos SDK version. -2. Due to differences between the Cosmos release series, each series will have its own specific API implementations of `Network` struct and `Adapter` interface. + a. The types and interfaces (`Client`, `OfflineClient`...), this separates design from implementation detail. + b. The `Server` functionality as this is independent of the Cosmos SDK version. + c. The `Online/OfflineNetwork`, which is not exported, and implements the rosetta API using the `Client` interface to query the node, build tx and so on. + d. The `errors` package to extend rosetta errors. +2. Due to differences between the Cosmos release series, each series will have its own specific implementation of `Client` interface. 3. There will be two options for starting an API service in applications: a. API shares the application process b. API-specific process. @@ -49,143 +52,130 @@ We will achieve these delivering on these principles by the following: As section will describe the proposed external library, including the service implementation, plus the defined types and interfaces. -#### Service +#### Server -`Service` is a simple `struct` that is started and listens to the port specified in the options. This is meant to be used across all the Cosmos SDK versions that are actively supported. +`Server` is a simple `struct` that is started and listens to the port specified in the settings. This is meant to be used across all the Cosmos SDK versions that are actively supported. The constructor follows: -`func New(options Options, network Network) (*Service, error)` - -#### Types - -`Service` accepts an `Options` `struct` that holds service configuration values, such as the port the service would be listening to: - -```golang -type Options struct { - ListenAddress string -} -``` - -The `Network` type holds network-specific properties (i.e. configuration values) and adapters. Pre-configured concrete types will be available for each Cosmos SDK release. Applications can also create their own custom types. - -```golang -type Network struct { - Properties rosetta.NetworkProperties - Adapter rosetta.Adapter -} -``` - -A `NetworkProperties` `struct` comprises basic values that are required by a Rosetta API `Service`: - -```golang -type NetworkProperties struct { - // Mandatory properties - Blockchain string - Network string - SupportedOperations []string +`func NewServer(settings Settings) (Server, error)` + +`Settings`, which are used to construct a new server, are the following: +```go +// Settings define the rosetta server settings +type Settings struct { + // Network contains the information regarding the network + Network *types.NetworkIdentifier + // Client is the online API handler + Client crgtypes.Client + // Listen is the address the handler will listen at + Listen string + // Offline defines if the rosetta service should be exposed in offline mode + Offline bool + // Retries is the number of readiness checks that will be attempted when instantiating the handler + // valid only for online API + Retries int + // RetryWait is the time that will be waited between retries + RetryWait time.Duration } ``` -Rosetta API services use `Blockchain` and `Network` as identifiers, e.g. the developers of _gaia_, the application that powers the Cosmos Hub, may want to set those to `Cosmos Hub` and `cosmos-hub-3` respectively. - -`SupportedOperations` contains the transaction types that are supported by the library. At the present time, -only `cosmos-sdk/MsgSend` is supported in Launchpad. Additional operations will be added in due time. - -For Launchpad we will map the amino type name to the operation supported, in Stargate we will use the protoc one. - -#### Interfaces - -Every SDK version uses a different format to connect (rpc, gRpc, etc), we have abstracted this in what is called the -Adapter. This is an interface that defines the methods an adapter implementation must provide in order to be used -in the `Network` interface. - -Each Cosmos SDK release series will have their own Adapter implementations. -Developers can implement their own custom adapters as required. - -```golang -type Adapter interface { - DataAPI - ConstructionAPI -} +#### Types -type DataAPI interface { - server.NetworkAPIServicer - server.AccountAPIServicer - server.MempoolAPIServicer - server.BlockAPIServicer - server.ConstructionAPIServicer +Package types uses a mixture of rosetta types and custom defined type wrappers, that the client must parse and return while executing operations. + + +##### Interfaces + +Every SDK version uses a different format to connect (rpc, gRPC, etc), query and build transactions, we have abstracted this in what is the `Client` interface. +The client uses rosetta types, whilst the `Online/OfflineNetwork` takes care of returning correctly parsed rosetta responses and errors. + +Each Cosmos SDK release series will have their own `Client` implementations. +Developers can implement their own custom `Client`s as required. + +```go +// Client defines the API the client implementation should provide. +type Client interface { + // Needed if the client needs to perform some action before connecting. + Bootstrap() error + // Ready checks if the servicer constraints for queries are satisfied + // for example the node might still not be ready, it's useful in process + // when the rosetta instance might come up before the node itself + // the servicer must return nil if the node is ready + Ready() error + + // Data API + + // Balances fetches the balance of the given address + // if height is not nil, then the balance will be displayed + // at the provided height, otherwise last block balance will be returned + Balances(ctx context.Context, addr string, height *int64) ([]*types.Amount, error) + // BlockByHashAlt gets a block and its transaction at the provided height + BlockByHash(ctx context.Context, hash string) (BlockResponse, error) + // BlockByHeightAlt gets a block given its height, if height is nil then last block is returned + BlockByHeight(ctx context.Context, height *int64) (BlockResponse, error) + // BlockTransactionsByHash gets the block, parent block and transactions + // given the block hash. + BlockTransactionsByHash(ctx context.Context, hash string) (BlockTransactionsResponse, error) + // BlockTransactionsByHash gets the block, parent block and transactions + // given the block hash. + BlockTransactionsByHeight(ctx context.Context, height *int64) (BlockTransactionsResponse, error) + // GetTx gets a transaction given its hash + GetTx(ctx context.Context, hash string) (*types.Transaction, error) + // GetUnconfirmedTx gets an unconfirmed Tx given its hash + // NOTE(fdymylja): NOT IMPLEMENTED YET! + GetUnconfirmedTx(ctx context.Context, hash string) (*types.Transaction, error) + // Mempool returns the list of the current non confirmed transactions + Mempool(ctx context.Context) ([]*types.TransactionIdentifier, error) + // Peers gets the peers currently connected to the node + Peers(ctx context.Context) ([]*types.Peer, error) + // Status returns the node status, such as sync data, version etc + Status(ctx context.Context) (*types.SyncStatus, error) + + // Construction API + + // PostTx posts txBytes to the node and returns the transaction identifier plus metadata related + // to the transaction itself. + PostTx(txBytes []byte) (res *types.TransactionIdentifier, meta map[string]interface{}, err error) + // ConstructionMetadataFromOptions + ConstructionMetadataFromOptions(ctx context.Context, options map[string]interface{}) (meta map[string]interface{}, err error) + OfflineClient } -type ConstructionAPI interface { - server.ConstructionAPIServicer +// OfflineClient defines the functionalities supported without having access to the node +type OfflineClient interface { + NetworkInformationProvider + // SignedTx returns the signed transaction given the tx bytes (msgs) plus the signatures + SignedTx(ctx context.Context, txBytes []byte, sigs []*types.Signature) (signedTxBytes []byte, err error) + // TxOperationsAndSignersAccountIdentifiers returns the operations related to a transaction and the account + // identifiers if the transaction is signed + TxOperationsAndSignersAccountIdentifiers(signed bool, hexBytes []byte) (ops []*types.Operation, signers []*types.AccountIdentifier, err error) + // ConstructionPayload returns the construction payload given the request + ConstructionPayload(ctx context.Context, req *types.ConstructionPayloadsRequest) (resp *types.ConstructionPayloadsResponse, err error) + // PreprocessOperationsToOptions returns the options given the preprocess operations + PreprocessOperationsToOptions(ctx context.Context, req *types.ConstructionPreprocessRequest) (options map[string]interface{}, err error) + // AccountIdentifierFromPublicKey returns the account identifier given the public key + AccountIdentifierFromPublicKey(pubKey *types.PublicKey) (*types.AccountIdentifier, error) } ``` -Example in pseudo-code of an Adapter interface: - -```golang -type SomeAdapter struct { - cosmosClient client - tendermintClient client -} - -func NewSomeAdapter(cosmosClient client, tendermintClient client) rosetta.Adapter { - return &SomeAdapter{cosmosClient: cosmosClient, tendermintClient: tendermintClient} -} - -func (s SomeAdapter) NetworkStatus(ctx context.Context, request *types.NetworkRequest) (*types.NetworkStatusResponse, *types.Error) { - resp := s.tendermintClient.CallStatus() - // ... Parse status Response - // build NetworkStatusResponse - return networkStatusResp, nil -} - -func (s SomeAdapter) AccountBalance(ctx context.Context, request *types.AccountBalanceRequest) (*types.AccountBalanceResponse, *types.Error) { - resp := s.cosmosClient.Account() - // ... Parse cosmos specific account response - // build AccountBalanceResponse - return AccountBalanceResponse, nil -} - -// And we repeat for all the methods defined in the interface. -``` +### 2. Cosmos SDK Implementation -For further information about the `Servicer` interfaces, please refer to the [Coinbase's rosetta-sdk-go's documentation](https://pkg.go.dev/github.com/coinbase/rosetta-sdk-go@v0.5.9/server). +The cosmos sdk implementation, based on version, takes care of satisfying the `Client` interface. +In Stargate, Launchpad and 0.37, we have introduced the concept of rosetta.Msg, this message is not in the shared repository as the sdk.Msg type differs between cosmos-sdk versions. -### 2. Cosmos SDK Implementation +The rosetta.Msg interface follows: -As described, each Cosmos SDK release series will have version specific implementations of `Network` and `Adapter`, as -well as a `NewNetwork` constructor. - -Due to separation of interface and implementation, application developers have the option to override as needed, -using this code as reference. - -```golang -// NewNetwork returns the default application configuration. -func NewNetwork(options Options) service.Network { - cosmosClient := cosmos.NewClient(fmt.Sprintf("http://%s", options.CosmosEndpoint)) - tendermintClient := tendermint.NewClient(fmt.Sprintf("http://%s", options.TendermintEndpoint)) - - return service.Network{ - Properties: rosetta.NetworkProperties{ - Blockchain: options.Blockchain, - Network: options.Network, - SupportedOperations: []string{OperationTransfer}, - }, - Adapter: newAdapter( - cosmosClient, - tendermintClient, - properties{ - Blockchain: options.Blockchain, - Network: options.Network, - OfflineMode: options.OfflineMode, - }, - ), - } +```go +// Msg represents a cosmos-sdk message that can be converted from and to a rosetta operation. +type Msg interface { + sdk.Msg + ToOperations(withStatus, hasError bool) []*types.Operation + FromOperations(ops []*types.Operation) (sdk.Msg, error) } ``` +Hence developers who want to extend the rosetta set of supported operations just need to extend their module's sdk.Msgs with the `ToOperations` and `FromOperations` methods. ### 3. API service invocation As stated at the start, application developers will have two methods for invocation of the Rosetta API service: @@ -195,67 +185,13 @@ As stated at the start, application developers will have two methods for invocat #### Shared Process (Only Stargate) -Rosetta API service could run within the same execution process as the application. New configuration option and -command line flags would be provided to support this: - -```golang - if config.Rosetta.Enable { - .... - get contecxt, flags, etc - ... - - h, err := service.New( - service.Options{ListenAddress: config.Rosetta.ListenAddress}, - rosetta.NewNetwork(cdc, options), - ) - if err != nil { - } - - ... - - go func() { - if err := h.Start(config); err != nil { - errCh <- err - } - }() - } +Rosetta API service could run within the same execution process as the application. This would be enabled via app.toml settings, and if gRPC is not enabled the rosetta instance would be spinned in offline mode (tx building capabilities only). -``` #### Separate API service -Client application developers can write a new command to launch a Rosetta API server as a separate process too: - -```golang -func RosettaCommand(cdc *codec.Codec) *cobra.Command { - - ... - cmd := &cobra.Command{ - Use: "rosetta", - .... - - RunE: func(cmd *cobra.Command, args []string) error { - .... - get contecxt, flags, etc - ... - - h, err := service.New( - service.Options{Endpoint: endpoint}, - rosetta.NewNetwork(cdc, options), - ) - if err != nil { - return err - } - - ... - - h.Start() - } - } - ... +Client application developers can write a new command to launch a Rosetta API server as a separate process too, using the rosetta command contained in the `/server/rosetta` package. Construction of the command depends on cosmos sdk version. Examples can be found inside `simd` for stargate, and `contrib/rosetta/simapp` for other release series. -} -``` ## Status diff --git a/docs/run-node/README.md b/docs/run-node/README.md index 0a2f24b87939..27ee9726508a 100644 --- a/docs/run-node/README.md +++ b/docs/run-node/README.md @@ -13,3 +13,4 @@ This folder contains documentation on how to run a node and interact with it. 1. [Interacting with a Node](./interact-node.md) 1. [Generating, Signing and Broadcasting Transactions](./txs.md) 1. [Cosmos Upgrade Manager](./cosmovisor.md) +1. [Rosetta API](./rosetta.md) diff --git a/docs/run-node/rosetta.md b/docs/run-node/rosetta.md new file mode 100644 index 000000000000..b10bc21e7996 --- /dev/null +++ b/docs/run-node/rosetta.md @@ -0,0 +1,83 @@ +# Rosetta + +Package rosetta implements the rosetta API for the current cosmos sdk release series. + +The client satisfies [cosmos-rosetta-gateway](https://github.com/tendermint/cosmos-rosetta-gateway) `Client` interface implementation. + +## Extension + +There are two ways in which you can customize and extend the implementation with your custom settings. + +### Message extension + +In order to make an `sdk.Msg` understandable by rosetta the only thing which is required is adding the methods to your message that satisfy the `rosetta.Msg` interface. +Examples on how to do so can be found in the staking types such as `MsgDelegate`, or in bank types such as `MsgSend`. + +### Client interface override + +In case more customization is required, it's possible to embed the Client type and override the methods which require customizations. + +Example: +```go +package custom_client +import ( + +"context" +"github.com/coinbase/rosetta-sdk-go/types" +"github.com/cosmos/cosmos-sdk/server/rosetta" +) + +// CustomClient embeds the standard cosmos client +// which means that it implements the cosmos-rosetta-gateway Client +// interface while at the same time allowing to customize certain methods +type CustomClient struct { + *rosetta.Client +} + +func (c *CustomClient) ConstructionPayload(_ context.Context, request *types.ConstructionPayloadsRequest) (resp *types.ConstructionPayloadsResponse, err error) { + // provide custom signature bytes + panic("implement me") +} +``` + +### Error extension + +Since rosetta requires to provide 'returned' errors to network options. In order to declare a new rosetta error, we use the `errors` package in cosmos-rosetta-gateway. + +Example: + +```go +package custom_errors +import crgerrs "github.com/tendermint/cosmos-rosetta-gateway/errors" + +var customErrRetriable = true +var CustomError = crgerrs.RegisterError(100, "custom message", customErrRetriable, "description") +``` + +Note: errors must be registered before cosmos-rosetta-gateway's `Server`.`Start` method is called. Otherwise the registration will be ignored. Errors with same code will be ignored too. + +## Integration in app.go + +To integrate rosetta as a command in your application, in app.go, in your root command simply use the `server.RosettaCommand` method. + +Example: + +```go +package app +import ( + +"github.com/cosmos/cosmos-sdk/server" +"github.com/spf13/cobra" +) + +func buildAppCommand(rootCmd *cobra.Command) { + // more app.go init stuff + // ... + // add rosetta command + rootCmd.AddCommand(server.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Marshaler)) +} +``` + +A full implementation example can be found in `simapp` package. + +NOTE: when using a customized client, the command cannot be used as the constructors required **may** differ, so it's required to create a new one. We intend to provide a way to init a customized client without writing extra code in the future. \ No newline at end of file diff --git a/go.mod b/go.mod index 323f13ebc44d..3e2c956f3544 100644 --- a/go.mod +++ b/go.mod @@ -4,18 +4,16 @@ module github.com/cosmos/cosmos-sdk require ( github.com/99designs/keyring v1.1.6 - github.com/DataDog/zstd v1.4.5 // indirect github.com/armon/go-metrics v0.3.6 github.com/bgentry/speakeasy v0.1.0 github.com/btcsuite/btcd v0.21.0-beta github.com/btcsuite/btcutil v1.0.2 + github.com/coinbase/rosetta-sdk-go v0.5.9 github.com/confio/ics23/go v0.6.3 github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/iavl v0.15.3 github.com/cosmos/ledger-cosmos-go v0.11.1 github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect - github.com/dgraph-io/ristretto v0.0.3 // indirect - github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 github.com/gogo/gateway v1.1.0 github.com/gogo/protobuf v1.3.3 @@ -31,7 +29,7 @@ require ( github.com/magiconair/properties v1.8.4 github.com/mattn/go-isatty v0.0.12 github.com/otiai10/copy v1.4.2 - github.com/pelletier/go-toml v1.8.0 // indirect + github.com/pelletier/go-toml v1.8.1 // indirect github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.8.0 github.com/prometheus/common v0.15.0 @@ -41,11 +39,12 @@ require ( github.com/spf13/afero v1.3.4 // indirect github.com/spf13/cast v1.3.1 github.com/spf13/cobra v1.1.1 - github.com/spf13/jwalterweatherman v1.1.0 // indirect; indirects + github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.7.1 github.com/stretchr/testify v1.7.0 github.com/tendermint/btcd v0.1.1 + github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc1 github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 github.com/tendermint/go-amino v0.16.0 github.com/tendermint/tendermint v0.34.3 @@ -54,6 +53,7 @@ require ( google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f google.golang.org/grpc v1.35.0 google.golang.org/protobuf v1.25.0 + gopkg.in/ini.v1 v1.61.0 // indirect gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index 21ae47248ee3..c99dd6b24c26 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,19 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/99designs/keyring v1.1.6 h1:kVDC2uCgVwecxCk+9zoCt2uEL6dt+dfVzMvGgnVcIuM= github.com/99designs/keyring v1.1.6/go.mod h1:16e0ds7LGQQcT59QqkTg72Hh5ShM51Byv5PEmW6uoRU= +github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -26,6 +39,8 @@ github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/Workiva/go-datastructures v1.0.52 h1:PLSK6pwn8mYdaoaCZEMsXBpBotr4HHn9abU0yMQt0NI= @@ -37,9 +52,11 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -48,6 +65,7 @@ github.com/armon/go-metrics v0.3.6/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -57,6 +75,7 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M= @@ -76,6 +95,7 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= @@ -83,9 +103,13 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coinbase/rosetta-sdk-go v0.5.8/go.mod h1:xd4wYUhV3LkY78SPH8BUhc88rXfn2jYgN9BfiSjbcvM= +github.com/coinbase/rosetta-sdk-go v0.5.9 h1:CuGQE3HFmYwdEACJnuOtVI9cofqPsGvq6FdFIzaOPKI= +github.com/coinbase/rosetta-sdk-go v0.5.9/go.mod h1:xd4wYUhV3LkY78SPH8BUhc88rXfn2jYgN9BfiSjbcvM= github.com/confio/ics23/go v0.0.0-20200817220745-f173e6211efb/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= github.com/confio/ics23/go v0.6.3 h1:PuGK2V1NJWZ8sSkNDq91jgT/cahFEW9RGp4Y5jxulf0= github.com/confio/ics23/go v0.6.3/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= @@ -120,6 +144,7 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= @@ -134,29 +159,39 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b h1:HBah4D48ypg3J7Np4N+HY/ZR76fx3HEUGxDU6Uk39oQ= github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= +github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 h1:2vLKys4RBU4pn2T/hjXMbvwTr1Cvy5THHrQkbeY9HRk= github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25/go.mod h1:hTr8+TLQmkUkgcuh3mcr5fjrT9c64ZzsBCdCEC6UppY= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum/go-ethereum v1.9.23 h1:SIKhg/z4Q7AbvqcxuPYvMxf36che/Rq/Pp0IdYEkbtw= +github.com/ethereum/go-ethereum v1.9.23/go.mod h1:JIfVb6esrqALTExdz9hRYvrP0xBDf6wCncIu1hNwHpM= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y= github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= @@ -164,6 +199,7 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -175,6 +211,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -207,6 +245,7 @@ github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.2-0.20200707131729-196ae77b8a26/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw= github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -218,9 +257,13 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64= +github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -241,8 +284,10 @@ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.1/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= @@ -293,13 +338,18 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= +github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/improbable-eng/grpc-web v0.13.0 h1:7XqtaBWaOCH0cVGKHyvhtcuo6fgW32Y10yRKrDHFHOc= github.com/improbable-eng/grpc-web v0.13.0/go.mod h1:6hRR09jOEG81ADP5wCQju1z71g6OL4eEvELdran/3cs= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -317,8 +367,10 @@ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d h1:Z+RDyXzjKE0i2sTjZ/b1uxiGtPhFy34Ou/Tk0qwN0kM= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -331,23 +383,36 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY= github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -365,6 +430,8 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8= +github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -374,6 +441,8 @@ github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ib github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= +github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= @@ -389,6 +458,8 @@ github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtb github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= @@ -420,11 +491,13 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw= -github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs= +github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= @@ -472,6 +545,7 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= @@ -482,11 +556,14 @@ github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzy github.com/regen-network/cosmos-proto v0.3.1/go.mod h1:jO0sVX6a1B36nmE8C9xBFXpNwWejXC7QqCOnH3O0+YM= github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= +github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.20.0 h1:38k9hgtUBdxFwE34yS8rTHmHBa4eN16E4DJlv177LNs= github.com/rs/zerolog v1.20.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo= @@ -497,6 +574,7 @@ github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0 github.com/sasha-s/go-deadlock v0.2.0 h1:lMqc+fUb7RrFS3gQLtoQsJ7/6TV/pAIFvBsqX73DK8Y= github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -535,6 +613,9 @@ github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/y github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= +github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -545,6 +626,7 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -556,6 +638,8 @@ github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzH github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s= github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U= +github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc1 h1:UEkXlFMcWdQWPOA/Rf8nV4WruMK7JO2U8iX7rMTuC24= +github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc1/go.mod h1:gBPw8WV2Erm4UGHlBRiM3zaEBst4bsuihmMCNQdgP/s= github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RMWx1aInLzndwxKalgi5rTqgfXxOxbEI= github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= @@ -568,13 +652,21 @@ github.com/tendermint/tendermint v0.34.3/go.mod h1:h57vnXeOlrdvvNFCqPBSaOrpOivl+ github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI= github.com/tendermint/tm-db v0.6.3 h1:ZkhQcKnB8/2jr5EaZwGndN4owkPsGezW2fSisS9zGbg= github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8= +github.com/tidwall/gjson v1.6.1/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0= +github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= +github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/sjson v1.1.2/go.mod h1:SEzaDwxiPzKzNfUEO4HbYF/m4UCSJDsGgNqsS1LvdoY= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vmihailenco/msgpack/v5 v5.0.0-beta.9/go.mod h1:HVxBVPUK/+fZMonk4bi1islLa8V3cfnBug0+4dykPzo= +github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= +github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -623,6 +715,7 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= @@ -636,15 +729,18 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -669,6 +765,7 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -681,6 +778,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -692,6 +790,7 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -713,12 +812,16 @@ golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -754,6 +857,7 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -818,9 +922,14 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.61.0 h1:LBCdW4FmFYL4s/vDZD1RQYX7oAR6IjujCYgMdbHBR10= +gopkg.in/ini.v1 v1.61.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -834,6 +943,9 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/server/config/config.go b/server/config/config.go index 68f6cf4352f6..8f1c47e88d2c 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -101,6 +101,29 @@ type APIConfig struct { // Ref: https://github.com/cosmos/cosmos-sdk/issues/6420 } +// RosettaConfig defines the Rosetta API listener configuration. +type RosettaConfig struct { + // Address defines the API server to listen on + Address string `mapstructure:"address"` + + // Blockchain defines the blockchain name + // defaults to DefaultBlockchain + Blockchain string `mapstructure:"blockchain"` + + // Network defines the network name + Network string `mapstructure:"network"` + + // Retries defines the maximum number of retries + // rosetta will do before quitting + Retries int `mapstructure:"retries"` + + // Enable defines if the API server should be enabled. + Enable bool `mapstructure:"enable"` + + // Offline defines if the server must be run in offline mode + Offline bool `mapstructure:"offline"` +} + // GRPCConfig defines configuration for the gRPC server. type GRPCConfig struct { // Enable defines if the gRPC server should be enabled. @@ -138,6 +161,7 @@ type Config struct { Telemetry telemetry.Config `mapstructure:"telemetry"` API APIConfig `mapstructure:"api"` GRPC GRPCConfig `mapstructure:"grpc"` + Rosetta RosettaConfig `mapstructure:"rosetta"` GRPCWeb GRPCWebConfig `mapstructure:"grpc-web"` StateSync StateSyncConfig `mapstructure:"state-sync"` } @@ -198,6 +222,14 @@ func DefaultConfig() *Config { Enable: true, Address: DefaultGRPCAddress, }, + Rosetta: RosettaConfig{ + Enable: false, + Address: ":8080", + Blockchain: "app", + Network: "network", + Retries: 3, + Offline: false, + }, GRPCWeb: GRPCWebConfig{ Enable: true, Address: DefaultGRPCWebAddress, @@ -252,6 +284,14 @@ func GetConfig(v *viper.Viper) Config { RPCMaxBodyBytes: v.GetUint("api.rpc-max-body-bytes"), EnableUnsafeCORS: v.GetBool("api.enabled-unsafe-cors"), }, + Rosetta: RosettaConfig{ + Enable: v.GetBool("rosetta.enable"), + Address: v.GetString("rosetta.address"), + Blockchain: v.GetString("rosetta.blockchain"), + Network: v.GetString("rosetta.network"), + Retries: v.GetInt("rosetta.retries"), + Offline: v.GetBool("rosetta.offline"), + }, GRPC: GRPCConfig{ Enable: v.GetBool("grpc.enable"), Address: v.GetString("grpc.address"), diff --git a/server/config/toml.go b/server/config/toml.go index 58dc7bfed2b4..88197defe91b 100644 --- a/server/config/toml.go +++ b/server/config/toml.go @@ -135,6 +135,30 @@ rpc-max-body-bytes = {{ .API.RPCMaxBodyBytes }} # EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk). enabled-unsafe-cors = {{ .API.EnableUnsafeCORS }} +############################################################################### +### Rosetta Configuration ### +############################################################################### + +[rosetta] + +# Enable defines if the Rosetta API server should be enabled. +enable = {{ .Rosetta.Enable }} + +# Address defines the Rosetta API server to listen on. +address = "{{ .Rosetta.Address }}" + +# Network defines the name of the blockchain that will be returned by Rosetta. +blockchain = "{{ .Rosetta.Blockchain }}" + +# Network defines the name of the network that will be returned by Rosetta. +network = "{{ .Rosetta.Network }}" + +# Retries defines the number of retries when connecting to the node before failing. +retries = {{ .Rosetta.Retries }} + +# Offline defines if Rosetta server should run in offline mode. +offline = {{ .Rosetta.Offline }} + ############################################################################### ### gRPC Configuration ### ############################################################################### diff --git a/server/rosetta.go b/server/rosetta.go new file mode 100644 index 000000000000..c6a928d062d0 --- /dev/null +++ b/server/rosetta.go @@ -0,0 +1,42 @@ +package server + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/server/rosetta" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" +) + +// RosettaCommand builds the rosetta root command given +// a protocol buffers serializer/deserializer +func RosettaCommand(ir codectypes.InterfaceRegistry, cdc codec.Marshaler) *cobra.Command { + cmd := &cobra.Command{ + Use: "rosetta", + Short: "spin up a rosetta server", + RunE: func(cmd *cobra.Command, args []string) error { + conf, err := rosetta.FromFlags(cmd.Flags()) + if err != nil { + return err + } + + protoCodec, ok := cdc.(*codec.ProtoCodec) + if !ok { + return fmt.Errorf("exoected *codec.ProtoMarshaler, got: %T", cdc) + } + conf.WithCodec(ir, protoCodec) + + rosettaSrv, err := rosetta.ServerFromConfig(conf) + if err != nil { + return err + } + return rosettaSrv.Start() + }, + } + rosetta.SetFlags(cmd.Flags()) + + return cmd +} diff --git a/server/rosetta/client_offline.go b/server/rosetta/client_offline.go new file mode 100644 index 000000000000..f619bfc6d2cf --- /dev/null +++ b/server/rosetta/client_offline.go @@ -0,0 +1,221 @@ +package rosetta + +import ( + "context" + "encoding/hex" + "strings" + + "github.com/btcsuite/btcd/btcec" + "github.com/coinbase/rosetta-sdk-go/types" + crgerrs "github.com/tendermint/cosmos-rosetta-gateway/errors" + "github.com/tendermint/tendermint/crypto" + + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" +) + +func (c *Client) OperationStatuses() []*types.OperationStatus { + return []*types.OperationStatus{ + { + Status: StatusSuccess, + Successful: true, + }, + { + Status: StatusReverted, + Successful: false, + }, + } +} + +func (c *Client) Version() string { + return c.version +} + +func (c *Client) SupportedOperations() []string { + var supportedOperations []string + for _, ii := range c.ir.ListImplementations("cosmos.base.v1beta1.Msg") { + resolve, err := c.ir.Resolve(ii) + if err != nil { + continue + } + + if _, ok := resolve.(Msg); ok { + supportedOperations = append(supportedOperations, strings.TrimLeft(ii, "/")) + } + } + + supportedOperations = append(supportedOperations, OperationFee) + + return supportedOperations +} + +func (c *Client) SignedTx(ctx context.Context, txBytes []byte, signatures []*types.Signature) (signedTxBytes []byte, err error) { + TxConfig := c.getTxConfig() + rawTx, err := TxConfig.TxDecoder()(txBytes) + if err != nil { + return nil, err + } + + txBldr, err := TxConfig.WrapTxBuilder(rawTx) + if err != nil { + return nil, err + } + + var sigs = make([]signing.SignatureV2, len(signatures)) + for i, signature := range signatures { + if signature.PublicKey.CurveType != types.Secp256k1 { + return nil, crgerrs.ErrUnsupportedCurve + } + + cmp, err := btcec.ParsePubKey(signature.PublicKey.Bytes, btcec.S256()) + if err != nil { + return nil, err + } + + compressedPublicKey := make([]byte, secp256k1.PubKeySize) + copy(compressedPublicKey, cmp.SerializeCompressed()) + pubKey := &secp256k1.PubKey{Key: compressedPublicKey} + + accountInfo, err := c.accountInfo(ctx, sdk.AccAddress(pubKey.Address()).String(), nil) + if err != nil { + return nil, err + } + + sig := signing.SignatureV2{ + PubKey: pubKey, + Data: &signing.SingleSignatureData{ + SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, + Signature: signature.Bytes, + }, + Sequence: accountInfo.GetSequence(), + } + sigs[i] = sig + } + + if err = txBldr.SetSignatures(sigs...); err != nil { + return nil, err + } + + txBytes, err = c.getTxConfig().TxEncoder()(txBldr.GetTx()) + if err != nil { + return nil, err + } + + return txBytes, nil +} + +func (c *Client) ConstructionPayload(_ context.Context, request *types.ConstructionPayloadsRequest) (resp *types.ConstructionPayloadsResponse, err error) { + // check if there is at least one operation + if len(request.Operations) < 1 { + return nil, crgerrs.WrapError(crgerrs.ErrInvalidOperation, "expected at least one operation") + } + + // convert rosetta operations to sdk msgs and fees (if present) + msgs, fee, err := opsToMsgsAndFees(c.ir, request.Operations) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrInvalidOperation, err.Error()) + } + + metadata, err := getMetadataFromPayloadReq(request) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, err.Error()) + } + + txFactory := tx.Factory{}.WithAccountNumber(metadata.AccountNumber).WithChainID(metadata.ChainID). + WithGas(metadata.Gas).WithSequence(metadata.Sequence).WithMemo(metadata.Memo).WithFees(fee.String()) + + TxConfig := c.getTxConfig() + txFactory = txFactory.WithTxConfig(TxConfig) + + txBldr, err := tx.BuildUnsignedTx(txFactory, msgs...) + if err != nil { + return nil, err + } + + // Sign_mode_legacy_amino is being used as default here, as sign_mode_direct + // needs the signer infos to be set before hand but rosetta doesn't have a way + // to do this yet. To be revisited in future versions of sdk and rosetta + if txFactory.SignMode() == signing.SignMode_SIGN_MODE_UNSPECIFIED { + txFactory = txFactory.WithSignMode(signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) + } + + signerData := authsigning.SignerData{ + ChainID: txFactory.ChainID(), + AccountNumber: txFactory.AccountNumber(), + Sequence: txFactory.Sequence(), + } + + signBytes, err := TxConfig.SignModeHandler().GetSignBytes(txFactory.SignMode(), signerData, txBldr.GetTx()) + if err != nil { + return nil, err + } + + txBytes, err := TxConfig.TxEncoder()(txBldr.GetTx()) + if err != nil { + return nil, err + } + + accIdentifiers := getAccountIdentifiersByMsgs(msgs) + + payloads := make([]*types.SigningPayload, len(accIdentifiers)) + for i, accID := range accIdentifiers { + payloads[i] = &types.SigningPayload{ + AccountIdentifier: accID, + Bytes: crypto.Sha256(signBytes), + SignatureType: types.Ecdsa, + } + } + + return &types.ConstructionPayloadsResponse{ + UnsignedTransaction: hex.EncodeToString(txBytes), + Payloads: payloads, + }, nil +} + +func getAccountIdentifiersByMsgs(msgs []sdk.Msg) []*types.AccountIdentifier { + var accIdentifiers []*types.AccountIdentifier + for _, msg := range msgs { + for _, signer := range msg.GetSigners() { + accIdentifiers = append(accIdentifiers, &types.AccountIdentifier{Address: signer.String()}) + } + } + + return accIdentifiers +} + +func (c *Client) PreprocessOperationsToOptions(_ context.Context, req *types.ConstructionPreprocessRequest) (options map[string]interface{}, err error) { + operations := req.Operations + if len(operations) < 1 { + return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, "invalid number of operations") + } + + msgs, err := opsToMsgs(c.ir, operations) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrInvalidOperation, err.Error()) + } + + if len(msgs) < 1 || len(msgs[0].GetSigners()) < 1 { + return nil, crgerrs.WrapError(crgerrs.ErrInvalidOperation, "operation produced no msg or signers") + } + + memo, ok := req.Metadata["memo"] + if !ok { + memo = "" + } + + defaultGas := float64(200000) + + gas := req.SuggestedFeeMultiplier + if gas == nil { + gas = &defaultGas + } + + return map[string]interface{}{ + OptionAddress: msgs[0].GetSigners()[0], + OptionMemo: memo, + OptionGas: gas, + }, nil +} diff --git a/server/rosetta/client_online.go b/server/rosetta/client_online.go new file mode 100644 index 000000000000..110430bb1806 --- /dev/null +++ b/server/rosetta/client_online.go @@ -0,0 +1,447 @@ +package rosetta + +import ( + "bytes" + "context" + "encoding/hex" + "fmt" + "strconv" + "time" + + "github.com/cosmos/cosmos-sdk/version" + + abcitypes "github.com/tendermint/tendermint/abci/types" + + "github.com/tendermint/btcd/btcec" + + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + + "github.com/coinbase/rosetta-sdk-go/types" + "google.golang.org/grpc/metadata" + + "github.com/tendermint/tendermint/rpc/client/http" + tmtypes "github.com/tendermint/tendermint/rpc/core/types" + "google.golang.org/grpc" + + crgerrs "github.com/tendermint/cosmos-rosetta-gateway/errors" + crgtypes "github.com/tendermint/cosmos-rosetta-gateway/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + grpctypes "github.com/cosmos/cosmos-sdk/types/grpc" + authclient "github.com/cosmos/cosmos-sdk/x/auth/client" + authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" + auth "github.com/cosmos/cosmos-sdk/x/auth/types" + bank "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +// interface assertion +var _ crgtypes.Client = (*Client)(nil) + +const tmWebsocketPath = "/websocket" +const defaultNodeTimeout = 15 * time.Second + +// Client implements a single network client to interact with cosmos based chains +type Client struct { + config *Config + + auth auth.QueryClient + bank bank.QueryClient + + ir codectypes.InterfaceRegistry + + clientCtx client.Context + + version string +} + +func (c *Client) AccountIdentifierFromPublicKey(pubKey *types.PublicKey) (*types.AccountIdentifier, error) { + if pubKey.CurveType != "secp256k1" { + return nil, crgerrs.WrapError(crgerrs.ErrUnsupportedCurve, "only secp256k1 supported") + } + + cmp, err := btcec.ParsePubKey(pubKey.Bytes, btcec.S256()) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, err.Error()) + } + + compressedPublicKey := make([]byte, secp256k1.PubKeySize) + copy(compressedPublicKey, cmp.SerializeCompressed()) + + pk := secp256k1.PubKey{Key: compressedPublicKey} + + return &types.AccountIdentifier{ + Address: sdk.AccAddress(pk.Address()).String(), + }, nil +} + +// NewClient instantiates a new online servicer +func NewClient(cfg *Config) (*Client, error) { + info := version.NewInfo() + + v := info.Version + if v == "" { + v = "unknown" + } + + return &Client{ + config: cfg, + ir: cfg.InterfaceRegistry, + version: fmt.Sprintf("%s/%s", info.AppName, v), + }, nil +} + +func (c *Client) accountInfo(ctx context.Context, addr string, height *int64) (auth.AccountI, error) { + if height != nil { + strHeight := strconv.FormatInt(*height, 10) + ctx = metadata.AppendToOutgoingContext(ctx, grpctypes.GRPCBlockHeightHeader, strHeight) + } + + accountInfo, err := c.auth.Account(ctx, &auth.QueryAccountRequest{ + Address: addr, + }) + if err != nil { + return nil, crgerrs.FromGRPCToRosettaError(err) + } + + var account auth.AccountI + err = c.ir.UnpackAny(accountInfo.Account, &account) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) + } + + return account, nil +} + +func (c *Client) Balances(ctx context.Context, addr string, height *int64) ([]*types.Amount, error) { + if height != nil { + strHeight := strconv.FormatInt(*height, 10) + ctx = metadata.AppendToOutgoingContext(ctx, grpctypes.GRPCBlockHeightHeader, strHeight) + } + + balance, err := c.bank.AllBalances(ctx, &bank.QueryAllBalancesRequest{ + Address: addr, + }) + if err != nil { + return nil, crgerrs.FromGRPCToRosettaError(err) + } + + availableCoins, err := c.coins(ctx) + if err != nil { + return nil, err + } + + return sdkCoinsToRosettaAmounts(balance.Balances, availableCoins), nil +} + +func (c *Client) BlockByHash(ctx context.Context, hash string) (crgtypes.BlockResponse, error) { + bHash, err := hex.DecodeString(hash) + if err != nil { + return crgtypes.BlockResponse{}, fmt.Errorf("invalid block hash: %s", err) + } + + block, err := c.clientCtx.Client.BlockByHash(ctx, bHash) + if err != nil { + return crgtypes.BlockResponse{}, err + } + + return buildBlockResponse(block), nil +} + +func (c *Client) BlockByHeight(ctx context.Context, height *int64) (crgtypes.BlockResponse, error) { + block, err := c.clientCtx.Client.Block(ctx, height) + if err != nil { + return crgtypes.BlockResponse{}, err + } + + return buildBlockResponse(block), nil +} + +func buildBlockResponse(block *tmtypes.ResultBlock) crgtypes.BlockResponse { + return crgtypes.BlockResponse{ + Block: TMBlockToRosettaBlockIdentifier(block), + ParentBlock: TMBlockToRosettaParentBlockIdentifier(block), + MillisecondTimestamp: timeToMilliseconds(block.Block.Time), + TxCount: int64(len(block.Block.Txs)), + } +} + +func (c *Client) BlockTransactionsByHash(ctx context.Context, hash string) (crgtypes.BlockTransactionsResponse, error) { + blockResp, err := c.BlockByHash(ctx, hash) + if err != nil { + return crgtypes.BlockTransactionsResponse{}, err + } + + txs, err := c.listTransactionsInBlock(ctx, blockResp.Block.Index) + if err != nil { + return crgtypes.BlockTransactionsResponse{}, err + } + + return crgtypes.BlockTransactionsResponse{ + BlockResponse: blockResp, + Transactions: sdkTxsWithHashToRosettaTxs(txs), + }, nil +} + +func (c *Client) BlockTransactionsByHeight(ctx context.Context, height *int64) (crgtypes.BlockTransactionsResponse, error) { + blockResp, err := c.BlockByHeight(ctx, height) + if err != nil { + return crgtypes.BlockTransactionsResponse{}, err + } + + txs, err := c.listTransactionsInBlock(ctx, blockResp.Block.Index) + if err != nil { + return crgtypes.BlockTransactionsResponse{}, err + } + + return crgtypes.BlockTransactionsResponse{ + BlockResponse: blockResp, + Transactions: sdkTxsWithHashToRosettaTxs(txs), + }, nil +} + +// Coins fetches the existing coins in the application +func (c *Client) coins(ctx context.Context) (sdk.Coins, error) { + supply, err := c.bank.TotalSupply(ctx, &bank.QueryTotalSupplyRequest{}) + if err != nil { + return nil, crgerrs.FromGRPCToRosettaError(err) + } + return supply.Supply, nil +} + +// listTransactionsInBlock returns the list of the transactions in a block given its height +func (c *Client) listTransactionsInBlock(ctx context.Context, height int64) ([]*sdkTxWithHash, error) { + txQuery := fmt.Sprintf(`tx.height=%d`, height) + txList, err := c.clientCtx.Client.TxSearch(ctx, txQuery, true, nil, nil, "") + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrUnknown, err.Error()) + } + + sdkTxs, err := tmResultTxsToSdkTxsWithHash(c.clientCtx.TxConfig.TxDecoder(), txList.Txs) + if err != nil { + return nil, err + } + return sdkTxs, nil +} + +func (c *Client) TxOperationsAndSignersAccountIdentifiers(signed bool, txBytes []byte) (ops []*types.Operation, signers []*types.AccountIdentifier, err error) { + txConfig := c.getTxConfig() + rawTx, err := txConfig.TxDecoder()(txBytes) + if err != nil { + return nil, nil, err + } + + txBldr, err := txConfig.WrapTxBuilder(rawTx) + if err != nil { + return nil, nil, err + } + + var accountIdentifierSigners []*types.AccountIdentifier + if signed { + addrs := txBldr.GetTx().GetSigners() + for _, addr := range addrs { + signer := &types.AccountIdentifier{ + Address: addr.String(), + } + accountIdentifierSigners = append(accountIdentifierSigners, signer) + } + } + + return sdkTxToOperations(txBldr.GetTx(), false, false), accountIdentifierSigners, nil +} + +// GetTx returns a transaction given its hash +func (c *Client) GetTx(_ context.Context, hash string) (*types.Transaction, error) { + txResp, err := authclient.QueryTx(c.clientCtx, hash) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrUnknown, err.Error()) + } + var sdkTx sdk.Tx + err = c.ir.UnpackAny(txResp.Tx, &sdkTx) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) + } + return sdkTxWithHashToOperations(&sdkTxWithHash{ + HexHash: txResp.TxHash, + Code: txResp.Code, + Log: txResp.RawLog, + Tx: sdkTx, + }), nil +} + +// GetUnconfirmedTx gets an unconfirmed transaction given its hash +func (c *Client) GetUnconfirmedTx(ctx context.Context, hash string) (*types.Transaction, error) { + res, err := c.clientCtx.Client.UnconfirmedTxs(ctx, nil) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrNotFound, "unconfirmed tx not found") + } + + hashAsBytes, err := hex.DecodeString(hash) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrInterpreting, "invalid hash") + } + + for _, tx := range res.Txs { + if bytes.Equal(tx.Hash(), hashAsBytes) { + sdkTx, err := tmTxToSdkTx(c.clientCtx.TxConfig.TxDecoder(), tx) + if err != nil { + return nil, err + } + + return &types.Transaction{ + TransactionIdentifier: TmTxToRosettaTxsIdentifier(tx), + Operations: sdkTxToOperations(sdkTx, false, false), + Metadata: nil, + }, nil + } + } + + return nil, crgerrs.WrapError(crgerrs.ErrNotFound, "transaction not found in mempool") +} + +// Mempool returns the unconfirmed transactions in the mempool +func (c *Client) Mempool(ctx context.Context) ([]*types.TransactionIdentifier, error) { + txs, err := c.clientCtx.Client.UnconfirmedTxs(ctx, nil) + if err != nil { + return nil, err + } + + return TMTxsToRosettaTxsIdentifiers(txs.Txs), nil +} + +// Peers gets the number of peers +func (c *Client) Peers(ctx context.Context) ([]*types.Peer, error) { + netInfo, err := c.clientCtx.Client.NetInfo(ctx) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrUnknown, err.Error()) + } + return TmPeersToRosettaPeers(netInfo.Peers), nil +} + +func (c *Client) Status(ctx context.Context) (*types.SyncStatus, error) { + status, err := c.clientCtx.Client.Status(ctx) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrUnknown, err.Error()) + } + return TMStatusToRosettaSyncStatus(status), err +} + +func (c *Client) getTxConfig() client.TxConfig { + return c.clientCtx.TxConfig +} + +func (c *Client) PostTx(txBytes []byte) (*types.TransactionIdentifier, map[string]interface{}, error) { + // sync ensures it will go through checkTx + res, err := c.clientCtx.BroadcastTxSync(txBytes) + if err != nil { + return nil, nil, crgerrs.WrapError(crgerrs.ErrUnknown, err.Error()) + } + // check if tx was broadcast successfully + if res.Code != abcitypes.CodeTypeOK { + return nil, nil, crgerrs.WrapError(crgerrs.ErrUnknown, fmt.Sprintf("transaction broadcast failure: (%d) %s ", res.Code, res.RawLog)) + } + + return &types.TransactionIdentifier{ + Hash: res.TxHash, + }, + map[string]interface{}{ + Log: res.RawLog, + }, nil +} + +func (c *Client) ConstructionMetadataFromOptions(ctx context.Context, options map[string]interface{}) (meta map[string]interface{}, err error) { + if len(options) == 0 { + return nil, crgerrs.ErrBadArgument + } + + addr, ok := options[OptionAddress] + if !ok { + return nil, crgerrs.WrapError(crgerrs.ErrInvalidAddress, "no address provided") + } + + addrString, ok := addr.(string) + if !ok { + return nil, crgerrs.WrapError(crgerrs.ErrInvalidAddress, "address is not a string") + } + + accountInfo, err := c.accountInfo(ctx, addrString, nil) + if err != nil { + return nil, err + } + + gas, ok := options[OptionGas] + if !ok { + return nil, crgerrs.WrapError(crgerrs.ErrInvalidAddress, "gas not set") + } + + memo, ok := options[OptionMemo] + if !ok { + return nil, crgerrs.WrapError(crgerrs.ErrInvalidMemo, "memo not set") + } + + status, err := c.clientCtx.Client.Status(ctx) + if err != nil { + return nil, err + } + + return map[string]interface{}{ + OptionAccountNumber: accountInfo.GetAccountNumber(), + OptionSequence: accountInfo.GetSequence(), + OptionChainID: status.NodeInfo.Network, + OptionGas: gas, + OptionMemo: memo, + }, nil +} + +func (c *Client) Ready() error { + ctx, cancel := context.WithTimeout(context.Background(), defaultNodeTimeout) + defer cancel() + _, err := c.clientCtx.Client.Health(ctx) + if err != nil { + return err + } + _, err = c.bank.TotalSupply(ctx, &bank.QueryTotalSupplyRequest{}) + if err != nil { + return err + } + return nil +} + +func (c *Client) Bootstrap() error { + grpcConn, err := grpc.Dial(c.config.GRPCEndpoint, grpc.WithInsecure()) + if err != nil { + return err + } + + tmRPC, err := http.New(c.config.TendermintRPC, tmWebsocketPath) + if err != nil { + return err + } + + authClient := auth.NewQueryClient(grpcConn) + bankClient := bank.NewQueryClient(grpcConn) + + // NodeURI and Client are set from here otherwise + // WitNodeURI will require to create a new client + // it's done here because WithNodeURI panics if + // connection to tendermint node fails + clientCtx := client.Context{ + Client: tmRPC, + NodeURI: c.config.TendermintRPC, + } + clientCtx = clientCtx. + WithJSONMarshaler(c.config.Codec). + WithInterfaceRegistry(c.config.InterfaceRegistry). + WithTxConfig(authtx.NewTxConfig(c.config.Codec, authtx.DefaultSignModes)). + WithAccountRetriever(auth.AccountRetriever{}). + WithBroadcastMode(flags.BroadcastBlock) + + c.auth = authClient + c.bank = bankClient + c.clientCtx = clientCtx + c.ir = c.config.InterfaceRegistry + + return nil +} diff --git a/server/rosetta/codec.go b/server/rosetta/codec.go new file mode 100644 index 000000000000..96242a9e044a --- /dev/null +++ b/server/rosetta/codec.go @@ -0,0 +1,22 @@ +package rosetta + +import ( + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + authcodec "github.com/cosmos/cosmos-sdk/x/auth/types" + bankcodec "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +// MakeCodec generates the codec required to interact +// with the cosmos APIs used by the rosetta gateway +func MakeCodec() (*codec.ProtoCodec, codectypes.InterfaceRegistry) { + ir := codectypes.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(ir) + + authcodec.RegisterInterfaces(ir) + bankcodec.RegisterInterfaces(ir) + cryptocodec.RegisterInterfaces(ir) + + return cdc, ir +} diff --git a/server/rosetta/config.go b/server/rosetta/config.go new file mode 100644 index 000000000000..a6a81669398d --- /dev/null +++ b/server/rosetta/config.go @@ -0,0 +1,203 @@ +package rosetta + +import ( + "fmt" + "strings" + "time" + + "github.com/coinbase/rosetta-sdk-go/types" + "github.com/spf13/pflag" + crg "github.com/tendermint/cosmos-rosetta-gateway/server" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" +) + +// configuration defaults constants +const ( + // DefaultBlockchain defines the default blockchain identifier name + DefaultBlockchain = "app" + // DefaultAddr defines the default rosetta binding address + DefaultAddr = ":8080" + // DefaultRetries is the default number of retries + DefaultRetries = 5 + // DefaultTendermintEndpoint is the default value for the tendermint endpoint + DefaultTendermintEndpoint = "localhost:26657" + // DefaultGRPCEndpoint is the default value for the gRPC endpoint + DefaultGRPCEndpoint = "localhost:9090" + // DefaultNetwork defines the default network name + DefaultNetwork = "network" + // DefaultOffline defines the default offline value + DefaultOffline = false +) + +// configuration flags +const ( + FlagBlockchain = "blockchain" + FlagNetwork = "network" + FlagTendermintEndpoint = "tendermint" + FlagGRPCEndpoint = "grpc" + FlagAddr = "addr" + FlagRetries = "retries" + FlagOffline = "offline" +) + +// Config defines the configuration of the rosetta server +type Config struct { + // Blockchain defines the blockchain name + // defaults to DefaultBlockchain + Blockchain string + // Network defines the network name + Network string + // TendermintRPC defines the endpoint to connect to + // tendermint RPC, specifying 'tcp://' before is not + // required, usually it's at port 26657 of the + TendermintRPC string + // GRPCEndpoint defines the cosmos application gRPC endpoint + // usually it is located at 9090 port + GRPCEndpoint string + // Addr defines the default address to bind the rosetta server to + // defaults to DefaultAddr + Addr string + // Retries defines the maximum number of retries + // rosetta will do before quitting + Retries int + // Offline defines if the server must be run in offline mode + Offline bool + // Codec overrides the default data and construction api client codecs + Codec *codec.ProtoCodec + // InterfaceRegistry overrides the default data and construction api interface registry + InterfaceRegistry codectypes.InterfaceRegistry +} + +// NetworkIdentifier returns the network identifier given the configuration +func (c *Config) NetworkIdentifier() *types.NetworkIdentifier { + return &types.NetworkIdentifier{ + Blockchain: c.Blockchain, + Network: c.Network, + } +} + +// validate validates a configuration and sets +// its defaults in case they were not provided +func (c *Config) validate() error { + if (c.Codec == nil) != (c.InterfaceRegistry == nil) { + return fmt.Errorf("codec and interface registry must be both different from nil or nil") + } + + if c.Addr == "" { + c.Addr = DefaultAddr + } + if c.Blockchain == "" { + c.Blockchain = DefaultBlockchain + } + if c.Retries == 0 { + c.Retries = DefaultRetries + } + // these are must + if c.Network == "" { + return fmt.Errorf("network not provided") + } + if c.Offline { + return fmt.Errorf("offline mode is not supported for stargate implementation due to how sigv2 works") + } + + // these are optional but it must be online + if c.GRPCEndpoint == "" { + return fmt.Errorf("grpc endpoint not provided") + } + if c.TendermintRPC == "" { + return fmt.Errorf("tendermint rpc not provided") + } + if !strings.HasPrefix(c.TendermintRPC, "tcp://") { + c.TendermintRPC = fmt.Sprintf("tcp://%s", c.TendermintRPC) + } + + return nil +} + +// WithCodec extends the configuration with a predefined Codec +func (c *Config) WithCodec(ir codectypes.InterfaceRegistry, cdc *codec.ProtoCodec) { + c.Codec = cdc + c.InterfaceRegistry = ir +} + +// FromFlags gets the configuration from flags +func FromFlags(flags *pflag.FlagSet) (*Config, error) { + blockchain, err := flags.GetString(FlagBlockchain) + if err != nil { + return nil, err + } + network, err := flags.GetString(FlagNetwork) + if err != nil { + return nil, err + } + tendermintRPC, err := flags.GetString(FlagTendermintEndpoint) + if err != nil { + return nil, err + } + gRPCEndpoint, err := flags.GetString(FlagGRPCEndpoint) + if err != nil { + return nil, err + } + addr, err := flags.GetString(FlagAddr) + if err != nil { + return nil, err + } + retries, err := flags.GetInt(FlagRetries) + if err != nil { + return nil, err + } + offline, err := flags.GetBool(FlagOffline) + if err != nil { + return nil, err + } + conf := &Config{ + Blockchain: blockchain, + Network: network, + TendermintRPC: tendermintRPC, + GRPCEndpoint: gRPCEndpoint, + Addr: addr, + Retries: retries, + Offline: offline, + } + err = conf.validate() + if err != nil { + return nil, err + } + return conf, nil +} + +func ServerFromConfig(conf *Config) (crg.Server, error) { + err := conf.validate() + if err != nil { + return crg.Server{}, err + } + client, err := NewClient(conf) + if err != nil { + return crg.Server{}, err + } + return crg.NewServer( + crg.Settings{ + Network: &types.NetworkIdentifier{ + Blockchain: conf.Blockchain, + Network: conf.Network, + }, + Client: client, + Listen: conf.Addr, + Offline: conf.Offline, + Retries: conf.Retries, + RetryWait: 15 * time.Second, + }) +} + +// SetFlags sets the configuration flags to the given flagset +func SetFlags(flags *pflag.FlagSet) { + flags.String(FlagBlockchain, DefaultBlockchain, "the blockchain type") + flags.String(FlagNetwork, DefaultNetwork, "the network name") + flags.String(FlagTendermintEndpoint, DefaultTendermintEndpoint, "the tendermint rpc endpoint, without tcp://") + flags.String(FlagGRPCEndpoint, DefaultGRPCEndpoint, "the app gRPC endpoint") + flags.String(FlagAddr, DefaultAddr, "the address rosetta will bind to") + flags.Int(FlagRetries, DefaultRetries, "the number of retries that will be done before quitting") + flags.Bool(FlagOffline, DefaultOffline, "run rosetta only with construction API") +} diff --git a/server/rosetta/conv_from_rosetta.go b/server/rosetta/conv_from_rosetta.go new file mode 100644 index 000000000000..da9ea5b2ed6f --- /dev/null +++ b/server/rosetta/conv_from_rosetta.go @@ -0,0 +1,211 @@ +package rosetta + +import ( + "fmt" + "time" + + "github.com/coinbase/rosetta-sdk-go/types" + tmcoretypes "github.com/tendermint/tendermint/rpc/core/types" + tmtypes "github.com/tendermint/tendermint/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// timeToMilliseconds converts time to milliseconds timestamp +func timeToMilliseconds(t time.Time) int64 { + return t.UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond)) +} + +// sdkCoinsToRosettaAmounts converts []sdk.Coin to rosetta amounts +// availableCoins keeps track of current available coins vs the coins +// owned by an address. This is required to support historical balances +// as rosetta expects them to be set to 0, if an address does not own them +func sdkCoinsToRosettaAmounts(ownedCoins []sdk.Coin, availableCoins sdk.Coins) []*types.Amount { + amounts := make([]*types.Amount, len(availableCoins)) + ownedCoinsMap := make(map[string]sdk.Int, len(availableCoins)) + + for _, ownedCoin := range ownedCoins { + ownedCoinsMap[ownedCoin.Denom] = ownedCoin.Amount + } + + for i, coin := range availableCoins { + value, owned := ownedCoinsMap[coin.Denom] + if !owned { + amounts[i] = &types.Amount{ + Value: sdk.NewInt(0).String(), + Currency: &types.Currency{ + Symbol: coin.Denom, + }, + } + continue + } + amounts[i] = &types.Amount{ + Value: value.String(), + Currency: &types.Currency{ + Symbol: coin.Denom, + }, + } + } + + return amounts +} + +// sdkTxsWithHashToRosettaTxs converts sdk transactions wrapped with their hash to rosetta transactions +func sdkTxsWithHashToRosettaTxs(txs []*sdkTxWithHash) []*types.Transaction { + converted := make([]*types.Transaction, len(txs)) + for i, tx := range txs { + converted[i] = sdkTxWithHashToOperations(tx) + } + + return converted +} + +func sdkTxWithHashToOperations(tx *sdkTxWithHash) *types.Transaction { + hasError := tx.Code != 0 + return &types.Transaction{ + TransactionIdentifier: &types.TransactionIdentifier{Hash: tx.HexHash}, + Operations: sdkTxToOperations(tx.Tx, true, hasError), + Metadata: map[string]interface{}{ + Log: tx.Log, + }, + } +} + +// sdkTxToOperations converts an sdk.Tx to rosetta operations +func sdkTxToOperations(tx sdk.Tx, withStatus, hasError bool) []*types.Operation { + var operations []*types.Operation + + msgOps := sdkMsgsToRosettaOperations(tx.GetMsgs(), withStatus, hasError) + operations = append(operations, msgOps...) + + feeTx := tx.(sdk.FeeTx) + feeOps := sdkFeeTxToOperations(feeTx, withStatus, len(msgOps)) + operations = append(operations, feeOps...) + + return operations +} + +// sdkFeeTxToOperations converts sdk.FeeTx to rosetta operations +func sdkFeeTxToOperations(feeTx sdk.FeeTx, withStatus bool, previousOps int) []*types.Operation { + feeCoins := feeTx.GetFee() + var ops []*types.Operation + if feeCoins != nil { + var feeOps = rosettaFeeOperationsFromCoins(feeCoins, feeTx.FeePayer().String(), withStatus, previousOps) + ops = append(ops, feeOps...) + } + + return ops +} + +// rosettaFeeOperationsFromCoins returns the list of rosetta fee operations given sdk coins +func rosettaFeeOperationsFromCoins(coins sdk.Coins, account string, withStatus bool, previousOps int) []*types.Operation { + feeOps := make([]*types.Operation, 0) + var status string + if withStatus { + status = StatusSuccess + } + + for i, coin := range coins { + op := &types.Operation{ + OperationIdentifier: &types.OperationIdentifier{ + Index: int64(previousOps + i), + }, + Type: OperationFee, + Status: status, + Account: &types.AccountIdentifier{ + Address: account, + }, + Amount: &types.Amount{ + Value: "-" + coin.Amount.String(), + Currency: &types.Currency{ + Symbol: coin.Denom, + }, + }, + } + + feeOps = append(feeOps, op) + } + + return feeOps +} + +// sdkMsgsToRosettaOperations converts sdk messages to rosetta operations +func sdkMsgsToRosettaOperations(msgs []sdk.Msg, withStatus bool, hasError bool) []*types.Operation { + var operations []*types.Operation + for _, msg := range msgs { + if rosettaMsg, ok := msg.(Msg); ok { + operations = append(operations, rosettaMsg.ToOperations(withStatus, hasError)...) + } + } + + return operations +} + +// TMTxsToRosettaTxsIdentifiers converts a tendermint raw transactions into an array of rosetta tx identifiers +func TMTxsToRosettaTxsIdentifiers(txs []tmtypes.Tx) []*types.TransactionIdentifier { + converted := make([]*types.TransactionIdentifier, len(txs)) + for i, tx := range txs { + converted[i] = TmTxToRosettaTxsIdentifier(tx) + } + + return converted +} + +// TmTxToRosettaTxsIdentifier converts a tendermint raw transaction into a rosetta tx identifier +func TmTxToRosettaTxsIdentifier(tx tmtypes.Tx) *types.TransactionIdentifier { + return &types.TransactionIdentifier{Hash: fmt.Sprintf("%x", tx.Hash())} +} + +// TMBlockToRosettaBlockIdentifier converts a tendermint result block to a rosetta block identifier +func TMBlockToRosettaBlockIdentifier(block *tmcoretypes.ResultBlock) *types.BlockIdentifier { + return &types.BlockIdentifier{ + Index: block.Block.Height, + Hash: block.Block.Hash().String(), + } +} + +// TmPeersToRosettaPeers converts tendermint peers to rosetta ones +func TmPeersToRosettaPeers(peers []tmcoretypes.Peer) []*types.Peer { + converted := make([]*types.Peer, len(peers)) + + for i, peer := range peers { + converted[i] = &types.Peer{ + PeerID: peer.NodeInfo.Moniker, + Metadata: map[string]interface{}{ + "addr": peer.NodeInfo.ListenAddr, + }, + } + } + + return converted +} + +// TMStatusToRosettaSyncStatus converts a tendermint status to rosetta sync status +func TMStatusToRosettaSyncStatus(status *tmcoretypes.ResultStatus) *types.SyncStatus { + // determine sync status + var stage = StageSynced + if status.SyncInfo.CatchingUp { + stage = StageSyncing + } + + return &types.SyncStatus{ + CurrentIndex: status.SyncInfo.LatestBlockHeight, + TargetIndex: nil, // sync info does not allow us to get target height + Stage: &stage, + } +} + +// TMBlockToRosettaParentBlockIdentifier returns the parent block identifier from the last block +func TMBlockToRosettaParentBlockIdentifier(block *tmcoretypes.ResultBlock) *types.BlockIdentifier { + if block.Block.Height == 1 { + return &types.BlockIdentifier{ + Index: 1, + Hash: fmt.Sprintf("%X", block.BlockID.Hash.Bytes()), + } + } + + return &types.BlockIdentifier{ + Index: block.Block.Height - 1, + Hash: fmt.Sprintf("%X", block.Block.LastBlockID.Hash.Bytes()), + } +} diff --git a/server/rosetta/conv_to_rosetta.go b/server/rosetta/conv_to_rosetta.go new file mode 100644 index 000000000000..09146eed4f3e --- /dev/null +++ b/server/rosetta/conv_to_rosetta.go @@ -0,0 +1,95 @@ +package rosetta + +import ( + "fmt" + "strconv" + "strings" + + "github.com/gogo/protobuf/jsonpb" + + "github.com/coinbase/rosetta-sdk-go/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// opsToMsgsAndFees converts rosetta operations to sdk.Msg and fees represented as sdk.Coins +func opsToMsgsAndFees(interfaceRegistry jsonpb.AnyResolver, ops []*types.Operation) ([]sdk.Msg, sdk.Coins, error) { + var feeAmnt []*types.Amount + var newOps []*types.Operation + var msgType string + // find the fee operation and put it aside + for _, op := range ops { + switch op.Type { + case OperationFee: + amount := op.Amount + feeAmnt = append(feeAmnt, amount) + default: + // check if operation matches the one already used + // as, at the moment, we only support operations + // that represent a single cosmos-sdk message + switch { + // if msgType was not set then set it + case msgType == "": + msgType = op.Type + // if msgType does not match op.Type then it means we're trying to send multiple messages in a single tx + case msgType != op.Type: + return nil, nil, fmt.Errorf("only single message operations are supported: %s - %s", msgType, op.Type) + } + // append operation to new ops list + newOps = append(newOps, op) + } + } + // convert all operations, except fee op to sdk.Msgs + msgs, err := opsToMsgs(interfaceRegistry, newOps) + if err != nil { + return nil, nil, err + } + + return msgs, amountsToCoins(feeAmnt), nil +} + +// amountsToCoins converts rosetta amounts to sdk coins +func amountsToCoins(amounts []*types.Amount) sdk.Coins { + var feeCoins sdk.Coins + + for _, amount := range amounts { + absValue := strings.Trim(amount.Value, "-") + value, err := strconv.ParseInt(absValue, 10, 64) + if err != nil { + return nil + } + coin := sdk.NewCoin(amount.Currency.Symbol, sdk.NewInt(value)) + feeCoins = append(feeCoins, coin) + } + + return feeCoins +} + +func opsToMsgs(interfaceRegistry jsonpb.AnyResolver, ops []*types.Operation) ([]sdk.Msg, error) { + var msgs []sdk.Msg + var operationsByType = make(map[string][]*types.Operation) + for _, op := range ops { + operationsByType[op.Type] = append(operationsByType[op.Type], op) + } + + for opName, operations := range operationsByType { + if opName == OperationFee { + continue + } + + msgType, err := interfaceRegistry.Resolve("/" + opName) // Types are registered as /proto-name in the interface registry. + if err != nil { + return nil, err + } + + if rosettaMsg, ok := msgType.(Msg); ok { + m, err := rosettaMsg.FromOperations(operations) + if err != nil { + return nil, err + } + msgs = append(msgs, m) + } + } + + return msgs, nil +} diff --git a/server/rosetta/types.go b/server/rosetta/types.go new file mode 100644 index 000000000000..626e7470ab91 --- /dev/null +++ b/server/rosetta/types.go @@ -0,0 +1,41 @@ +package rosetta + +import ( + "github.com/coinbase/rosetta-sdk-go/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// statuses +const ( + StatusSuccess = "Success" + StatusReverted = "Reverted" + StageSynced = "synced" + StageSyncing = "syncing" +) + +// misc +const ( + Log = "log" +) + +// operations +const ( + OperationFee = "fee" +) + +// options +const ( + OptionAccountNumber = "account_number" + OptionAddress = "address" + OptionChainID = "chain_id" + OptionSequence = "sequence" + OptionMemo = "memo" + OptionGas = "gas" +) + +type Msg interface { + sdk.Msg + ToOperations(withStatus, hasError bool) []*types.Operation + FromOperations(ops []*types.Operation) (sdk.Msg, error) +} diff --git a/server/rosetta/util.go b/server/rosetta/util.go new file mode 100644 index 000000000000..29e4a1587dc2 --- /dev/null +++ b/server/rosetta/util.go @@ -0,0 +1,112 @@ +package rosetta + +import ( + "fmt" + + "github.com/coinbase/rosetta-sdk-go/types" + + tmcoretypes "github.com/tendermint/tendermint/rpc/core/types" + tmtypes "github.com/tendermint/tendermint/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// tmResultTxsToSdkTxsWithHash converts tendermint result txs to cosmos sdk.Tx +func tmResultTxsToSdkTxsWithHash(decode sdk.TxDecoder, txs []*tmcoretypes.ResultTx) ([]*sdkTxWithHash, error) { + converted := make([]*sdkTxWithHash, len(txs)) + for i, tx := range txs { + sdkTx, err := decode(tx.Tx) + if err != nil { + return nil, err + } + converted[i] = &sdkTxWithHash{ + HexHash: fmt.Sprintf("%X", tx.Tx.Hash()), + Code: tx.TxResult.Code, + Log: tx.TxResult.Log, + Tx: sdkTx, + } + } + + return converted, nil +} + +func tmTxToSdkTx(decode sdk.TxDecoder, tx tmtypes.Tx) (sdk.Tx, error) { + sdkTx, err := decode(tx) + if err != nil { + return nil, err + } + + return sdkTx, err +} + +type sdkTxWithHash struct { + HexHash string + Code uint32 + Log string + Tx sdk.Tx +} + +type PayloadReqMetadata struct { + ChainID string + Sequence uint64 + AccountNumber uint64 + Gas uint64 + Memo string +} + +// getMetadataFromPayloadReq obtains the metadata from the request to /construction/payloads endpoint. +func getMetadataFromPayloadReq(req *types.ConstructionPayloadsRequest) (*PayloadReqMetadata, error) { + chainID, ok := req.Metadata[OptionChainID].(string) + if !ok { + return nil, fmt.Errorf("chain_id metadata was not provided") + } + + sequence, ok := req.Metadata[OptionSequence] + if !ok { + return nil, fmt.Errorf("sequence metadata was not provided") + } + + seqNum, ok := sequence.(float64) + if !ok { + return nil, fmt.Errorf("invalid sequence value") + } + + accountNum, ok := req.Metadata[OptionAccountNumber] + if !ok { + return nil, fmt.Errorf("account_number metadata was not provided") + } + + accNum, ok := accountNum.(float64) + if !ok { + fmt.Printf("this is type %T", accountNum) + return nil, fmt.Errorf("invalid account_number value") + } + + gasNum, ok := req.Metadata[OptionGas] + if !ok { + return nil, fmt.Errorf("gas metadata was not provided") + } + + gasF64, ok := gasNum.(float64) + if !ok { + return nil, fmt.Errorf("invalid gas value") + } + + memo, ok := req.Metadata[OptionMemo] + if !ok { + memo = "" + } + + memoStr, ok := memo.(string) + if !ok { + return nil, fmt.Errorf("invalid memo") + } + + return &PayloadReqMetadata{ + ChainID: chainID, + Sequence: uint64(seqNum), + AccountNumber: uint64(accNum), + Gas: uint64(gasF64), + Memo: memoStr, + }, nil +} diff --git a/server/start.go b/server/start.go index 84c4dc858651..447497f08708 100644 --- a/server/start.go +++ b/server/start.go @@ -9,7 +9,14 @@ import ( "runtime/pprof" "time" + "github.com/cosmos/cosmos-sdk/server/rosetta" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/spf13/cobra" + "google.golang.org/grpc" + + crgserver "github.com/tendermint/cosmos-rosetta-gateway/server" "github.com/tendermint/tendermint/abci/server" tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" tmos "github.com/tendermint/tendermint/libs/os" @@ -18,7 +25,6 @@ import ( pvm "github.com/tendermint/tendermint/privval" "github.com/tendermint/tendermint/proxy" "github.com/tendermint/tendermint/rpc/client/local" - "google.golang.org/grpc" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" @@ -280,7 +286,6 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App } var apiSrv *api.Server - if config.API.Enable { genDoc, err := genDocProvider() if err != nil { @@ -326,6 +331,42 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App } } + var rosettaSrv crgserver.Server + if config.Rosetta.Enable { + offlineMode := config.Rosetta.Offline + if !config.GRPC.Enable { // If GRPC is not enabled rosetta cannot work in online mode, so it works in offline mode. + offlineMode = true + } + + conf := &rosetta.Config{ + Blockchain: config.Rosetta.Blockchain, + Network: config.Rosetta.Network, + TendermintRPC: ctx.Config.RPC.ListenAddress, + GRPCEndpoint: config.GRPC.Address, + Addr: config.Rosetta.Address, + Retries: config.Rosetta.Retries, + Offline: offlineMode, + } + conf.WithCodec(clientCtx.InterfaceRegistry, clientCtx.JSONMarshaler.(*codec.ProtoCodec)) + + rosettaSrv, err = rosetta.ServerFromConfig(conf) + if err != nil { + return err + } + errCh := make(chan error) + go func() { + if err := rosettaSrv.Start(); err != nil { + errCh <- err + } + }() + + select { + case err := <-errCh: + return err + case <-time.After(5 * time.Second): // assume server started successfully + } + } + defer func() { if tmNode.IsRunning() { _ = tmNode.Stop() diff --git a/simapp/simd/cmd/root.go b/simapp/simd/cmd/root.go index e7713a284543..f76948d59cd5 100644 --- a/simapp/simd/cmd/root.go +++ b/simapp/simd/cmd/root.go @@ -90,6 +90,9 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) { txCommand(), keys.Commands(simapp.DefaultNodeHome), ) + + // add rosetta + rootCmd.AddCommand(server.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Marshaler)) } func addModuleInitFlags(startCmd *cobra.Command) { diff --git a/types/tx/types.go b/types/tx/types.go index 0392b2fcfd08..a0b05b5dcea0 100644 --- a/types/tx/types.go +++ b/types/tx/types.go @@ -132,6 +132,37 @@ func (t *Tx) GetSigners() []sdk.AccAddress { return signers } +func (t *Tx) GetGas() uint64 { + return t.AuthInfo.Fee.GasLimit +} +func (t *Tx) GetFee() sdk.Coins { + return t.AuthInfo.Fee.Amount +} +func (t *Tx) FeePayer() sdk.AccAddress { + feePayer := t.AuthInfo.Fee.Payer + if feePayer != "" { + payerAddr, err := sdk.AccAddressFromBech32(feePayer) + if err != nil { + panic(err) + } + return payerAddr + } + // use first signer as default if no payer specified + return t.GetSigners()[0] +} + +func (t *Tx) FeeGranter() sdk.AccAddress { + feePayer := t.AuthInfo.Fee.Granter + if feePayer != "" { + granterAddr, err := sdk.AccAddressFromBech32(feePayer) + if err != nil { + panic(err) + } + return granterAddr + } + return nil +} + // UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method func (t *Tx) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { if t.Body != nil { diff --git a/x/auth/client/cli/cli_test.go b/x/auth/client/cli/cli_test.go index fdd558b7971f..d8913d1ac07e 100644 --- a/x/auth/client/cli/cli_test.go +++ b/x/auth/client/cli/cli_test.go @@ -435,7 +435,7 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() { // Write the output to disk signedTxFile := testutil.WriteToNewTempFile(s.T(), signedTx.String()) - // Validate Signature + // validate Signature res, err = authtest.TxValidateSignaturesExec(val1.ClientCtx, signedTxFile.Name()) s.Require().NoError(err) s.Require().True(strings.Contains(res.String(), "[OK]")) diff --git a/x/auth/client/cli/validate_sigs.go b/x/auth/client/cli/validate_sigs.go index 52290ed8e95f..d8d6283a7990 100644 --- a/x/auth/client/cli/validate_sigs.go +++ b/x/auth/client/cli/validate_sigs.go @@ -16,7 +16,7 @@ import ( func GetValidateSignaturesCommand() *cobra.Command { cmd := &cobra.Command{ Use: "validate-signatures [file]", - Short: "Validate transactions signatures", + Short: "validate transactions signatures", Long: `Print the addresses that must sign the transaction, those who have already signed it, and make sure that signatures are in the correct order. @@ -96,7 +96,7 @@ func printAndValidateSigs( success = false } - // Validate the actual signature over the transaction bytes since we can + // validate the actual signature over the transaction bytes since we can // reach out to a full node to query accounts. if !offline && success { accNum, accSeq, err := clientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, sigAddr) diff --git a/x/bank/types/msgs.go b/x/bank/types/msgs.go index 22fdc30b3886..dd41975468ca 100644 --- a/x/bank/types/msgs.go +++ b/x/bank/types/msgs.go @@ -1,6 +1,13 @@ package types import ( + "fmt" + "strconv" + "strings" + + "github.com/coinbase/rosetta-sdk-go/types" + "github.com/gogo/protobuf/proto" + sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -62,6 +69,83 @@ func (msg MsgSend) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{from} } +// Rosetta interface +func (msg *MsgSend) ToOperations(withStatus bool, hasError bool) []*types.Operation { + var operations []*types.Operation + + fromAddress := msg.FromAddress + toAddress := msg.ToAddress + amounts := msg.Amount + if len(amounts) == 0 { + return []*types.Operation{} + } + + coin := amounts[0] + sendOp := func(account, amount string, index int) *types.Operation { + var status string + if withStatus { + status = "Success" + if hasError { + status = "Reverted" + } + } + return &types.Operation{ + OperationIdentifier: &types.OperationIdentifier{ + Index: int64(index), + }, + Type: proto.MessageName(msg), + Status: status, + Account: &types.AccountIdentifier{ + Address: account, + }, + Amount: &types.Amount{ + Value: amount, + Currency: &types.Currency{ + Symbol: coin.Denom, + }, + }, + } + } + operations = append(operations, + sendOp(fromAddress, "-"+coin.Amount.String(), 0), + sendOp(toAddress, coin.Amount.String(), 1), + ) + + return operations +} + +func (msg MsgSend) FromOperations(ops []*types.Operation) (sdk.Msg, error) { + var ( + from, to sdk.AccAddress + sendAmt sdk.Coin + err error + ) + + for _, op := range ops { + if strings.HasPrefix(op.Amount.Value, "-") { + from, err = sdk.AccAddressFromBech32(op.Account.Address) + if err != nil { + return nil, err + } + continue + } + + to, err = sdk.AccAddressFromBech32(op.Account.Address) + if err != nil { + return nil, err + } + + amount, err := strconv.ParseInt(op.Amount.Value, 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid amount") + } + + sendAmt = sdk.NewCoin(op.Amount.Currency.Symbol, sdk.NewInt(amount)) + } + + return NewMsgSend(from, to, sdk.NewCoins(sendAmt)), nil +} + var _ sdk.Msg = &MsgMultiSend{} // NewMsgMultiSend - construct arbitrary multi-in, multi-out send msg. diff --git a/x/distribution/types/msg.go b/x/distribution/types/msg.go index 8dc72081e9ac..62c8bfc2abbb 100644 --- a/x/distribution/types/msg.go +++ b/x/distribution/types/msg.go @@ -2,6 +2,12 @@ package types import ( + "fmt" + + rosettatypes "github.com/coinbase/rosetta-sdk-go/types" + "github.com/gogo/protobuf/proto" + + "github.com/cosmos/cosmos-sdk/server/rosetta" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -90,6 +96,50 @@ func (msg MsgWithdrawDelegatorReward) ValidateBasic() error { return nil } +func (msg *MsgWithdrawDelegatorReward) ToOperations(withStatus, hasError bool) []*rosettatypes.Operation { + + var status string + if withStatus { + status = rosetta.StatusSuccess + if hasError { + status = rosetta.StatusReverted + } + } + + op := &rosettatypes.Operation{ + OperationIdentifier: &rosettatypes.OperationIdentifier{ + Index: 0, + }, + RelatedOperations: nil, + Type: proto.MessageName(msg), + Status: status, + Account: &rosettatypes.AccountIdentifier{ + Address: msg.DelegatorAddress, + SubAccount: &rosettatypes.SubAccountIdentifier{ + Address: msg.ValidatorAddress, + }, + }, + } + return []*rosettatypes.Operation{op} +} + +func (msg *MsgWithdrawDelegatorReward) FromOperations(ops []*rosettatypes.Operation) (sdk.Msg, error) { + if len(ops) != 1 { + return nil, fmt.Errorf("expected one operation") + } + op := ops[0] + if op.Account == nil { + return nil, fmt.Errorf("account identifier must be specified") + } + if op.Account.SubAccount == nil { + return nil, fmt.Errorf("account identifier subaccount must be specified") + } + return &MsgWithdrawDelegatorReward{ + DelegatorAddress: op.Account.Address, + ValidatorAddress: op.Account.SubAccount.Address, + }, nil +} + func NewMsgWithdrawValidatorCommission(valAddr sdk.ValAddress) *MsgWithdrawValidatorCommission { return &MsgWithdrawValidatorCommission{ ValidatorAddress: valAddr.String(), diff --git a/x/genutil/client/cli/gentx_test.go b/x/genutil/client/cli/gentx_test.go index d15ee8896265..b5733675951a 100644 --- a/x/genutil/client/cli/gentx_test.go +++ b/x/genutil/client/cli/gentx_test.go @@ -72,7 +72,7 @@ func (s *IntegrationTestSuite) TestGenTxCmd() { err := cmd.ExecuteContext(ctx) s.Require().NoError(err) - // Validate generated transaction. + // validate generated transaction. open, err := os.Open(genTxFile) s.Require().NoError(err) diff --git a/x/ibc/core/03-connection/types/msgs_test.go b/x/ibc/core/03-connection/types/msgs_test.go index 57c1925f66db..6aff3b0904b3 100644 --- a/x/ibc/core/03-connection/types/msgs_test.go +++ b/x/ibc/core/03-connection/types/msgs_test.go @@ -138,7 +138,7 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenTry() { {"invalid counterparty client ID", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "test/conn1", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, {"invalid nil counterparty client", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", nil, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, {"invalid client unpacking", &types.MsgConnectionOpenTry{connectionID, "clienttotesta", invalidAny, counterparty, 500, []*types.Version{ibctesting.ConnectionVersion}, clientHeight, suite.proof, suite.proof, suite.proof, clientHeight, signer.String()}, false}, - {"counterparty failed Validate", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", invalidClient, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, + {"counterparty failed validate", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", invalidClient, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, {"empty counterparty prefix", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", clientState, emptyPrefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, {"empty counterpartyVersions", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, {"empty proofInit", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, emptyProof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, @@ -188,7 +188,7 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenAck() { {"invalid counterparty connection ID", types.NewMsgConnectionOpenAck(connectionID, "test/conn1", clientState, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, {"invalid nil counterparty client", types.NewMsgConnectionOpenAck(connectionID, connectionID, nil, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, {"invalid unpacking counterparty client", &types.MsgConnectionOpenAck{connectionID, connectionID, ibctesting.ConnectionVersion, invalidAny, clientHeight, suite.proof, suite.proof, suite.proof, clientHeight, signer.String()}, false}, - {"counterparty client failed Validate", types.NewMsgConnectionOpenAck(connectionID, connectionID, invalidClient, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, + {"counterparty client failed validate", types.NewMsgConnectionOpenAck(connectionID, connectionID, invalidClient, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, {"empty proofTry", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, emptyProof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, {"empty proofClient", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, emptyProof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, {"empty proofConsensus", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, emptyProof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, diff --git a/x/slashing/client/rest/rest.go b/x/slashing/client/rest/rest.go index a3a88545900b..059cb17c6bdc 100644 --- a/x/slashing/client/rest/rest.go +++ b/x/slashing/client/rest/rest.go @@ -3,9 +3,8 @@ package rest import ( "github.com/gorilla/mux" - "github.com/cosmos/cosmos-sdk/client/rest" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/rest" ) func RegisterHandlers(clientCtx client.Context, rtr *mux.Router) { diff --git a/x/staking/client/rest/rest.go b/x/staking/client/rest/rest.go index 35bb8da68139..6f9b7e1e2a60 100644 --- a/x/staking/client/rest/rest.go +++ b/x/staking/client/rest/rest.go @@ -3,9 +3,8 @@ package rest import ( "github.com/gorilla/mux" - "github.com/cosmos/cosmos-sdk/client/rest" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/rest" ) func RegisterHandlers(clientCtx client.Context, rtr *mux.Router) { diff --git a/x/staking/types/msg.go b/x/staking/types/msg.go index 2525aa66468f..52ab1750b827 100644 --- a/x/staking/types/msg.go +++ b/x/staking/types/msg.go @@ -2,9 +2,17 @@ package types import ( "bytes" + "fmt" + "strconv" + "strings" + + "github.com/gogo/protobuf/proto" + + rosettatypes "github.com/coinbase/rosetta-sdk-go/types" codectypes "github.com/cosmos/cosmos-sdk/codec/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/server/rosetta" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -249,6 +257,90 @@ func (msg MsgDelegate) ValidateBasic() error { return nil } +// Rosetta Msg interface. +func (msg *MsgDelegate) ToOperations(withStatus bool, hasError bool) []*rosettatypes.Operation { + var operations []*rosettatypes.Operation + delAddr := msg.DelegatorAddress + valAddr := msg.ValidatorAddress + coin := msg.Amount + delOp := func(account *rosettatypes.AccountIdentifier, amount string, index int) *rosettatypes.Operation { + var status string + if withStatus { + status = rosetta.StatusSuccess + if hasError { + status = rosetta.StatusReverted + } + } + return &rosettatypes.Operation{ + OperationIdentifier: &rosettatypes.OperationIdentifier{ + Index: int64(index), + }, + Type: proto.MessageName(msg), + Status: status, + Account: account, + Amount: &rosettatypes.Amount{ + Value: amount, + Currency: &rosettatypes.Currency{ + Symbol: coin.Denom, + }, + }, + } + } + delAcc := &rosettatypes.AccountIdentifier{ + Address: delAddr, + } + valAcc := &rosettatypes.AccountIdentifier{ + Address: "staking_account", + SubAccount: &rosettatypes.SubAccountIdentifier{ + Address: valAddr, + }, + } + operations = append(operations, + delOp(delAcc, "-"+coin.Amount.String(), 0), + delOp(valAcc, coin.Amount.String(), 1), + ) + return operations +} + +func (msg *MsgDelegate) FromOperations(ops []*rosettatypes.Operation) (sdk.Msg, error) { + var ( + delAddr sdk.AccAddress + valAddr sdk.ValAddress + sendAmt sdk.Coin + err error + ) + + for _, op := range ops { + if strings.HasPrefix(op.Amount.Value, "-") { + if op.Account == nil { + return nil, fmt.Errorf("account identifier must be specified") + } + delAddr, err = sdk.AccAddressFromBech32(op.Account.Address) + if err != nil { + return nil, err + } + continue + } + + if op.Account.SubAccount == nil { + return nil, fmt.Errorf("account identifier subaccount must be specified") + } + valAddr, err = sdk.ValAddressFromBech32(op.Account.SubAccount.Address) + if err != nil { + return nil, err + } + + amount, err := strconv.ParseInt(op.Amount.Value, 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid amount: %w", err) + } + + sendAmt = sdk.NewCoin(op.Amount.Currency.Symbol, sdk.NewInt(amount)) + } + + return NewMsgDelegate(delAddr, valAddr, sendAmt), nil +} + // NewMsgBeginRedelegate creates a new MsgBeginRedelegate instance. //nolint:interfacer func NewMsgBeginRedelegate( @@ -304,6 +396,103 @@ func (msg MsgBeginRedelegate) ValidateBasic() error { return nil } +// Rosetta Msg interface. +func (msg *MsgBeginRedelegate) ToOperations(withStatus bool, hasError bool) []*rosettatypes.Operation { + var operations []*rosettatypes.Operation + delAddr := msg.DelegatorAddress + srcValAddr := msg.ValidatorSrcAddress + destValAddr := msg.ValidatorDstAddress + coin := msg.Amount + delOp := func(account *rosettatypes.AccountIdentifier, amount string, index int) *rosettatypes.Operation { + var status string + if withStatus { + status = rosetta.StatusSuccess + if hasError { + status = rosetta.StatusReverted + } + } + return &rosettatypes.Operation{ + OperationIdentifier: &rosettatypes.OperationIdentifier{ + Index: int64(index), + }, + Type: proto.MessageName(msg), + Status: status, + Account: account, + Amount: &rosettatypes.Amount{ + Value: amount, + Currency: &rosettatypes.Currency{ + Symbol: coin.Denom, + }, + }, + } + } + srcValAcc := &rosettatypes.AccountIdentifier{ + Address: delAddr, + SubAccount: &rosettatypes.SubAccountIdentifier{ + Address: srcValAddr, + }, + } + destValAcc := &rosettatypes.AccountIdentifier{ + Address: "staking_account", + SubAccount: &rosettatypes.SubAccountIdentifier{ + Address: destValAddr, + }, + } + operations = append(operations, + delOp(srcValAcc, "-"+coin.Amount.String(), 0), + delOp(destValAcc, coin.Amount.String(), 1), + ) + return operations +} + +func (msg *MsgBeginRedelegate) FromOperations(ops []*rosettatypes.Operation) (sdk.Msg, error) { + var ( + delAddr sdk.AccAddress + srcValAddr sdk.ValAddress + destValAddr sdk.ValAddress + sendAmt sdk.Coin + err error + ) + + for _, op := range ops { + if strings.HasPrefix(op.Amount.Value, "-") { + if op.Account == nil { + return nil, fmt.Errorf("account identifier must be specified") + } + delAddr, err = sdk.AccAddressFromBech32(op.Account.Address) + if err != nil { + return nil, err + } + + if op.Account.SubAccount == nil { + return nil, fmt.Errorf("account identifier subaccount must be specified") + } + srcValAddr, err = sdk.ValAddressFromBech32(op.Account.SubAccount.Address) + if err != nil { + return nil, err + } + continue + } + + if op.Account.SubAccount == nil { + return nil, fmt.Errorf("account identifier subaccount must be specified") + } + destValAddr, err = sdk.ValAddressFromBech32(op.Account.SubAccount.Address) + if err != nil { + return nil, err + } + + amount, err := strconv.ParseInt(op.Amount.Value, 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid amount: %w", err) + } + + sendAmt = sdk.NewCoin(op.Amount.Currency.Symbol, sdk.NewInt(amount)) + } + + return NewMsgBeginRedelegate(delAddr, srcValAddr, destValAddr, sendAmt), nil +} + // NewMsgUndelegate creates a new MsgUndelegate instance. //nolint:interfacer func NewMsgUndelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount sdk.Coin) *MsgUndelegate { @@ -351,3 +540,88 @@ func (msg MsgUndelegate) ValidateBasic() error { return nil } + +// Rosetta Msg interface. +func (msg *MsgUndelegate) ToOperations(withStatus bool, hasError bool) []*rosettatypes.Operation { + var operations []*rosettatypes.Operation + delAddr := msg.DelegatorAddress + valAddr := msg.ValidatorAddress + coin := msg.Amount + delOp := func(account *rosettatypes.AccountIdentifier, amount string, index int) *rosettatypes.Operation { + var status string + if withStatus { + status = rosetta.StatusSuccess + if hasError { + status = rosetta.StatusReverted + } + } + return &rosettatypes.Operation{ + OperationIdentifier: &rosettatypes.OperationIdentifier{ + Index: int64(index), + }, + Type: proto.MessageName(msg), + Status: status, + Account: account, + Amount: &rosettatypes.Amount{ + Value: amount, + Currency: &rosettatypes.Currency{ + Symbol: coin.Denom, + }, + }, + } + } + delAcc := &rosettatypes.AccountIdentifier{ + Address: delAddr, + } + valAcc := &rosettatypes.AccountIdentifier{ + Address: "staking_account", + SubAccount: &rosettatypes.SubAccountIdentifier{ + Address: valAddr, + }, + } + operations = append(operations, + delOp(valAcc, "-"+coin.Amount.String(), 0), + delOp(delAcc, coin.Amount.String(), 1), + ) + return operations +} + +func (msg *MsgUndelegate) FromOperations(ops []*rosettatypes.Operation) (sdk.Msg, error) { + var ( + delAddr sdk.AccAddress + valAddr sdk.ValAddress + undelAmt sdk.Coin + err error + ) + + for _, op := range ops { + if strings.HasPrefix(op.Amount.Value, "-") { + if op.Account.SubAccount == nil { + return nil, fmt.Errorf("account identifier subaccount must be specified") + } + valAddr, err = sdk.ValAddressFromBech32(op.Account.SubAccount.Address) + if err != nil { + return nil, err + } + continue + } + + if op.Account == nil { + return nil, fmt.Errorf("account identifier must be specified") + } + + delAddr, err = sdk.AccAddressFromBech32(op.Account.Address) + if err != nil { + return nil, err + } + + amount, err := strconv.ParseInt(op.Amount.Value, 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid amount") + } + + undelAmt = sdk.NewCoin(op.Amount.Currency.Symbol, sdk.NewInt(amount)) + } + + return NewMsgUndelegate(delAddr, valAddr, undelAmt), nil +} diff --git a/x/staking/types/tx.pb.go b/x/staking/types/tx.pb.go index 50e1765ff6c0..fad3a8c75e14 100644 --- a/x/staking/types/tx.pb.go +++ b/x/staking/types/tx.pb.go @@ -6,6 +6,11 @@ package types import ( context "context" fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + time "time" + types "github.com/cosmos/cosmos-sdk/codec/types" github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" types1 "github.com/cosmos/cosmos-sdk/types" @@ -18,10 +23,6 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" - io "io" - math "math" - math_bits "math/bits" - time "time" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/upgrade/client/rest/rest.go b/x/upgrade/client/rest/rest.go index 3192083f8da4..8f104852496c 100644 --- a/x/upgrade/client/rest/rest.go +++ b/x/upgrade/client/rest/rest.go @@ -3,9 +3,8 @@ package rest import ( "github.com/gorilla/mux" - "github.com/cosmos/cosmos-sdk/client/rest" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/rest" ) // RegisterRoutes registers REST routes for the upgrade module under the path specified by routeName. From 78703f1b6ea1b173fbacb68462e41ca301bbf3d8 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Thu, 21 Jan 2021 13:35:40 +0100 Subject: [PATCH 068/152] remove any.ClearCachedValue method (#8402) * remove any.ClearCachedValue method This method is in a public interface but used only for tests. It shouldn't be used - `Any` values shouldn't be manipulated. This could lead to bugs. * rename any_test.go Co-authored-by: Alessio Treglia --- codec/types/any.go | 5 --- codec/types/any_internal_test.go | 53 ++++++++++++++++++++++++++++++++ codec/types/types_test.go | 11 ++----- 3 files changed, 55 insertions(+), 14 deletions(-) create mode 100644 codec/types/any_internal_test.go diff --git a/codec/types/any.go b/codec/types/any.go index eebf13ca6cf0..c33931f0e22f 100644 --- a/codec/types/any.go +++ b/codec/types/any.go @@ -113,8 +113,3 @@ func (any *Any) pack(x proto.Message) error { func (any *Any) GetCachedValue() interface{} { return any.cachedValue } - -// ClearCachedValue clears the cached value from the Any -func (any *Any) ClearCachedValue() { - any.cachedValue = nil -} diff --git a/codec/types/any_internal_test.go b/codec/types/any_internal_test.go new file mode 100644 index 000000000000..fda205f591ca --- /dev/null +++ b/codec/types/any_internal_test.go @@ -0,0 +1,53 @@ +package types + +import ( + "testing" + + "github.com/gogo/protobuf/proto" + "github.com/stretchr/testify/require" +) + +type Dog struct { + Name string `protobuf:"bytes,1,opt,name=size,proto3" json:"size,omitempty"` +} + +func (d Dog) Greet() string { return d.Name } + +// We implement a minimal proto.Message interface +func (d *Dog) Reset() { d.Name = "" } +func (d *Dog) String() string { return d.Name } +func (d *Dog) ProtoMessage() {} +func (d *Dog) XXX_MessageName() string { return "tests/dog" } + +type Animal interface { + Greet() string +} + +var _ Animal = (*Dog)(nil) +var _ proto.Message = (*Dog)(nil) + +func TestAnyPackUnpack(t *testing.T) { + registry := NewInterfaceRegistry() + registry.RegisterInterface("Animal", (*Animal)(nil)) + registry.RegisterImplementations( + (*Animal)(nil), + &Dog{}, + ) + + spot := &Dog{Name: "Spot"} + var animal Animal + + // with cache + any, err := NewAnyWithValue(spot) + require.NoError(t, err) + require.Equal(t, spot, any.GetCachedValue()) + err = registry.UnpackAny(any, &animal) + require.NoError(t, err) + require.Equal(t, spot, animal) + + // without cache + any.cachedValue = nil + err = registry.UnpackAny(any, &animal) + require.NoError(t, err) + require.Equal(t, spot, animal) +} diff --git a/codec/types/types_test.go b/codec/types/types_test.go index b2d014269502..43f85375508e 100644 --- a/codec/types/types_test.go +++ b/codec/types/types_test.go @@ -9,16 +9,15 @@ import ( "github.com/gogo/protobuf/grpc" "github.com/gogo/protobuf/jsonpb" "github.com/gogo/protobuf/proto" - grpc2 "google.golang.org/grpc" - "github.com/stretchr/testify/require" + grpc2 "google.golang.org/grpc" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/testutil/testdata" ) -func TestPackUnpack(t *testing.T) { +func TestAnyPackUnpack(t *testing.T) { registry := testdata.NewTestInterfaceRegistry() spot := &testdata.Dog{Name: "Spot"} @@ -31,12 +30,6 @@ func TestPackUnpack(t *testing.T) { err = registry.UnpackAny(any, &animal) require.NoError(t, err) require.Equal(t, spot, animal) - - // without cache - any.ClearCachedValue() - err = registry.UnpackAny(any, &animal) - require.NoError(t, err) - require.Equal(t, spot, animal) } type TestI interface { From f9ee39f0b2b9c548ea74c207567e9a2643d2c9dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Thu, 21 Jan 2021 16:10:07 +0100 Subject: [PATCH 069/152] Reorder IBC channel callbacks (#8404) * reorder chan callbacks * add changelog * Update CHANGELOG.md Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- CHANGELOG.md | 1 + x/ibc/core/keeper/msg_server.go | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2bc793c0511..3cfe96782b3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks. ### Bug Fixes diff --git a/x/ibc/core/keeper/msg_server.go b/x/ibc/core/keeper/msg_server.go index 5ea590fea93a..dcddcaed16d4 100644 --- a/x/ibc/core/keeper/msg_server.go +++ b/x/ibc/core/keeper/msg_server.go @@ -326,15 +326,15 @@ func (k Keeper) ChannelOpenAck(goCtx context.Context, msg *channeltypes.MsgChann return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) } - if err = cbs.OnChanOpenAck(ctx, msg.PortId, msg.ChannelId, msg.CounterpartyVersion); err != nil { - return nil, sdkerrors.Wrap(err, "channel open ack callback failed") - } - _, err = channel.HandleMsgChannelOpenAck(ctx, k.ChannelKeeper, cap, msg) if err != nil { return nil, err } + if err = cbs.OnChanOpenAck(ctx, msg.PortId, msg.ChannelId, msg.CounterpartyVersion); err != nil { + return nil, sdkerrors.Wrap(err, "channel open ack callback failed") + } + return &channeltypes.MsgChannelOpenAckResponse{}, nil } @@ -354,15 +354,15 @@ func (k Keeper) ChannelOpenConfirm(goCtx context.Context, msg *channeltypes.MsgC return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) } - if err = cbs.OnChanOpenConfirm(ctx, msg.PortId, msg.ChannelId); err != nil { - return nil, sdkerrors.Wrap(err, "channel open confirm callback failed") - } - _, err = channel.HandleMsgChannelOpenConfirm(ctx, k.ChannelKeeper, cap, msg) if err != nil { return nil, err } + if err = cbs.OnChanOpenConfirm(ctx, msg.PortId, msg.ChannelId); err != nil { + return nil, sdkerrors.Wrap(err, "channel open confirm callback failed") + } + return &channeltypes.MsgChannelOpenConfirmResponse{}, nil } From 5ed11519e0193396a05dec49871a6db3a0942086 Mon Sep 17 00:00:00 2001 From: Frojdi Dymylja <33157909+fdymylja@users.noreply.github.com> Date: Fri, 22 Jan 2021 05:12:22 +0100 Subject: [PATCH 070/152] [appd] fix: gRPC web address default flag value (#8399) * fix: flags grpc web default address * chore: update CHANGELOG.md Co-authored-by: SaReN Co-authored-by: Alessio Treglia --- CHANGELOG.md | 1 + server/start.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cfe96782b3d..eade4838160c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes +* (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value ## [v0.40.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.1) - 2021-01-19 diff --git a/server/start.go b/server/start.go index 447497f08708..764a67be52f4 100644 --- a/server/start.go +++ b/server/start.go @@ -160,7 +160,7 @@ which accepts a path for the resulting pprof file. cmd.Flags().String(flagGRPCAddress, config.DefaultGRPCAddress, "the gRPC server address to listen on") cmd.Flags().Bool(flagGRPCWebEnable, true, "Define if the gRPC-Web server should be enabled. (Note: gRPC must also be enabled.)") - cmd.Flags().String(flagGRPCWebAddress, config.DefaultGRPCAddress, "The gRPC-Web server address to listen on") + cmd.Flags().String(flagGRPCWebAddress, config.DefaultGRPCWebAddress, "The gRPC-Web server address to listen on") cmd.Flags().Uint64(FlagStateSyncSnapshotInterval, 0, "State sync snapshot interval") cmd.Flags().Uint32(FlagStateSyncSnapshotKeepRecent, 2, "State sync snapshot to keep") From 31fdee0228bd6f3e787489c8e4434aabc8facb7d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Jan 2021 10:36:46 -0300 Subject: [PATCH 071/152] build(deps): bump github.com/tendermint/cosmos-rosetta-gateway (#8408) Bumps [github.com/tendermint/cosmos-rosetta-gateway](https://github.com/tendermint/cosmos-rosetta-gateway) from 0.3.0-rc1 to 0.3.0-rc2. - [Release notes](https://github.com/tendermint/cosmos-rosetta-gateway/releases) - [Changelog](https://github.com/tendermint/cosmos-rosetta-gateway/blob/develop/CHANGELOG.md) - [Commits](https://github.com/tendermint/cosmos-rosetta-gateway/compare/v0.3.0-rc1...v0.3.0-rc2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3e2c956f3544..1b56715dee82 100644 --- a/go.mod +++ b/go.mod @@ -44,7 +44,7 @@ require ( github.com/spf13/viper v1.7.1 github.com/stretchr/testify v1.7.0 github.com/tendermint/btcd v0.1.1 - github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc1 + github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2 github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 github.com/tendermint/go-amino v0.16.0 github.com/tendermint/tendermint v0.34.3 diff --git a/go.sum b/go.sum index c99dd6b24c26..b36fb8fad57b 100644 --- a/go.sum +++ b/go.sum @@ -638,8 +638,8 @@ github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzH github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s= github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U= -github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc1 h1:UEkXlFMcWdQWPOA/Rf8nV4WruMK7JO2U8iX7rMTuC24= -github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc1/go.mod h1:gBPw8WV2Erm4UGHlBRiM3zaEBst4bsuihmMCNQdgP/s= +github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2 h1:crekJuQ57yIBDuKd3/dMJ00ZvOHURuv9RGJSi2hWTW4= +github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2/go.mod h1:gBPw8WV2Erm4UGHlBRiM3zaEBst4bsuihmMCNQdgP/s= github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RMWx1aInLzndwxKalgi5rTqgfXxOxbEI= github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= From 7d4f7f93febb442f13ca6a1486e841a9df9e3453 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Fri, 22 Jan 2021 21:44:54 -0300 Subject: [PATCH 072/152] x/bank: balance and metadata validation (#8417) * x/bank: balance validation * metadata validation * minor change * balance and metadata tests * changelog * check for empty coins * genesis test --- CHANGELOG.md | 3 +- x/bank/module.go | 2 +- x/bank/types/balance.go | 93 ++++++++++++++++++++ x/bank/types/balance_test.go | 80 ++++++++++++++++++ x/bank/types/genesis.go | 74 ++++++---------- x/bank/types/genesis_test.go | 152 +++++++++++++++++++++++++++------ x/bank/types/metadata.go | 56 ++++++++++++ x/bank/types/metadata_test.go | 155 ++++++++++++++++++++++++++++++++++ x/bank/types/supply.go | 4 +- 9 files changed, 542 insertions(+), 77 deletions(-) create mode 100644 x/bank/types/balance.go create mode 100644 x/bank/types/balance_test.go create mode 100644 x/bank/types/metadata.go create mode 100644 x/bank/types/metadata_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index eade4838160c..96b8f5629e1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,10 +38,11 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements -* (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks. +* (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks. ### Bug Fixes +* (x/bank) [\#8417](https://github.com/cosmos/cosmos-sdk/pull/8417) Validate balances and coin denom metadata on genesis * (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value ## [v0.40.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.1) - 2021-01-19 diff --git a/x/bank/module.go b/x/bank/module.go index bc998634c12e..f271fa21975c 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -58,7 +58,7 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONMarshaler, _ client.TxEncodi return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) } - return types.ValidateGenesis(data) + return data.Validate() } // RegisterRESTRoutes registers the REST routes for the bank module. diff --git a/x/bank/types/balance.go b/x/bank/types/balance.go new file mode 100644 index 000000000000..93517a1d925b --- /dev/null +++ b/x/bank/types/balance.go @@ -0,0 +1,93 @@ +package types + +import ( + "bytes" + "encoding/json" + fmt "fmt" + "sort" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank/exported" +) + +var _ exported.GenesisBalance = (*Balance)(nil) + +// GetAddress returns the account address of the Balance object. +func (b Balance) GetAddress() sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(b.Address) + return addr +} + +// GetCoins returns the account coins of the Balance object. +func (b Balance) GetCoins() sdk.Coins { + return b.Coins +} + +// Validate checks for address and coins correctness. +func (b Balance) Validate() error { + _, err := sdk.AccAddressFromBech32(b.Address) + if err != nil { + return err + } + + if len(b.Coins) == 0 { + return fmt.Errorf("empty or nil coins for address %s", b.Address) + } + + seenDenoms := make(map[string]bool) + + // NOTE: we perform a custom validation since the coins.Validate function + // errors on zero balance coins + for _, coin := range b.Coins { + if seenDenoms[coin.Denom] { + return fmt.Errorf("duplicate denomination %s", coin.Denom) + } + + if err := sdk.ValidateDenom(coin.Denom); err != nil { + return err + } + + if coin.IsNegative() { + return fmt.Errorf("coin %s amount is cannot be negative", coin.Denom) + } + + seenDenoms[coin.Denom] = true + } + + // sort the coins post validation + b.Coins = b.Coins.Sort() + + return nil +} + +// SanitizeGenesisBalances sorts addresses and coin sets. +func SanitizeGenesisBalances(balances []Balance) []Balance { + sort.Slice(balances, func(i, j int) bool { + addr1, _ := sdk.AccAddressFromBech32(balances[i].Address) + addr2, _ := sdk.AccAddressFromBech32(balances[j].Address) + return bytes.Compare(addr1.Bytes(), addr2.Bytes()) < 0 + }) + + for _, balance := range balances { + balance.Coins = balance.Coins.Sort() + } + + return balances +} + +// GenesisBalancesIterator implements genesis account iteration. +type GenesisBalancesIterator struct{} + +// IterateGenesisBalances iterates over all the genesis balances found in +// appGenesis and invokes a callback on each genesis account. If any call +// returns true, iteration stops. +func (GenesisBalancesIterator) IterateGenesisBalances( + cdc codec.JSONMarshaler, appState map[string]json.RawMessage, cb func(exported.GenesisBalance) (stop bool), +) { + for _, balance := range GetGenesisStateFromAppState(cdc, appState).Balances { + if cb(balance) { + break + } + } +} diff --git a/x/bank/types/balance_test.go b/x/bank/types/balance_test.go new file mode 100644 index 000000000000..73e4d8eff387 --- /dev/null +++ b/x/bank/types/balance_test.go @@ -0,0 +1,80 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestBalanceValidate(t *testing.T) { + + testCases := []struct { + name string + balance Balance + expErr bool + }{ + { + "valid balance", + Balance{ + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + Coins: sdk.Coins{sdk.NewInt64Coin("uatom", 1)}, + }, + false, + }, + {"empty balance", Balance{}, true}, + { + "nil balance coins", + Balance{ + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + }, + true, + }, + { + "dup coins", + Balance{ + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + Coins: sdk.Coins{ + sdk.NewInt64Coin("uatom", 1), + sdk.NewInt64Coin("uatom", 1), + }, + }, + true, + }, + { + "invalid coin denom", + Balance{ + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + Coins: sdk.Coins{ + sdk.Coin{Denom: "", Amount: sdk.OneInt()}, + }, + }, + true, + }, + { + "negative coin", + Balance{ + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + Coins: sdk.Coins{ + sdk.Coin{Denom: "uatom", Amount: sdk.NewInt(-1)}, + }, + }, + true, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + + err := tc.balance.Validate() + + if tc.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/x/bank/types/genesis.go b/x/bank/types/genesis.go index ccf35be86231..4adc758f3bd9 100644 --- a/x/bank/types/genesis.go +++ b/x/bank/types/genesis.go @@ -1,51 +1,49 @@ package types import ( - "bytes" "encoding/json" - "sort" + "fmt" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/bank/exported" ) -var _ exported.GenesisBalance = (*Balance)(nil) +// Validate performs basic validation of supply genesis data returning an +// error for any failed validation criteria. +func (gs GenesisState) Validate() error { + if err := gs.Params.Validate(); err != nil { + return err + } -// GetAddress returns the account address of the Balance object. -func (b Balance) GetAddress() sdk.AccAddress { - addr1, _ := sdk.AccAddressFromBech32(b.Address) - return addr1 -} + seenBalances := make(map[string]bool) + seenMetadatas := make(map[string]bool) -// GetAddress returns the account coins of the Balance object. -func (b Balance) GetCoins() sdk.Coins { - return b.Coins -} + for _, balance := range gs.Balances { + if seenBalances[balance.Address] { + return fmt.Errorf("duplicate balance for address %s", balance.Address) + } -// SanitizeGenesisAccounts sorts addresses and coin sets. -func SanitizeGenesisBalances(balances []Balance) []Balance { - sort.Slice(balances, func(i, j int) bool { - addr1, _ := sdk.AccAddressFromBech32(balances[i].Address) - addr2, _ := sdk.AccAddressFromBech32(balances[j].Address) - return bytes.Compare(addr1.Bytes(), addr2.Bytes()) < 0 - }) + if err := balance.Validate(); err != nil { + return err + } - for _, balance := range balances { - balance.Coins = balance.Coins.Sort() + seenBalances[balance.Address] = true } - return balances -} + for _, metadata := range gs.DenomMetadata { + if seenMetadatas[metadata.Base] { + return fmt.Errorf("duplicate client metadata for denom %s", metadata.Base) + } -// ValidateGenesis performs basic validation of supply genesis data returning an -// error for any failed validation criteria. -func ValidateGenesis(data GenesisState) error { - if err := data.Params.Validate(); err != nil { - return err + if err := metadata.Validate(); err != nil { + return err + } + + seenMetadatas[metadata.Base] = true } - return NewSupply(data.Supply).ValidateBasic() + // NOTE: this errors if supply for any given coin is zero + return NewSupply(gs.Supply).ValidateBasic() } // NewGenesisState creates a new genesis state. @@ -74,19 +72,3 @@ func GetGenesisStateFromAppState(cdc codec.JSONMarshaler, appState map[string]js return &genesisState } - -// GenesisAccountIterator implements genesis account iteration. -type GenesisBalancesIterator struct{} - -// IterateGenesisAccounts iterates over all the genesis accounts found in -// appGenesis and invokes a callback on each genesis account. If any call -// returns true, iteration stops. -func (GenesisBalancesIterator) IterateGenesisBalances( - cdc codec.JSONMarshaler, appState map[string]json.RawMessage, cb func(exported.GenesisBalance) (stop bool), -) { - for _, balance := range GetGenesisStateFromAppState(cdc, appState).Balances { - if cb(balance) { - break - } - } -} diff --git a/x/bank/types/genesis_test.go b/x/bank/types/genesis_test.go index 5f612aed726b..634b247e0190 100644 --- a/x/bank/types/genesis_test.go +++ b/x/bank/types/genesis_test.go @@ -1,52 +1,150 @@ -package types_test +package types import ( "testing" "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/x/bank/types" + sdk "github.com/cosmos/cosmos-sdk/types" ) -func TestMarshalJSONMetaData(t *testing.T) { - cdc := codec.NewLegacyAmino() +func TestGenesisStateValidate(t *testing.T) { testCases := []struct { - name string - input []types.Metadata - strOutput string + name string + genesisState GenesisState + expErr bool }{ - {"nil metadata", nil, `null`}, - {"empty metadata", []types.Metadata{}, `[]`}, - {"non-empty coins", []types.Metadata{{ - Description: "The native staking token of the Cosmos Hub.", - DenomUnits: []*types.DenomUnit{ - {"uatom", uint32(0), []string{"microatom"}}, // The default exponent value 0 is omitted in the json - {"matom", uint32(3), []string{"milliatom"}}, - {"atom", uint32(6), nil}, + { + "valid genesisState", + GenesisState{ + Params: DefaultParams(), + Balances: []Balance{ + { + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + Coins: sdk.Coins{sdk.NewInt64Coin("uatom", 1)}, + }, + }, + Supply: sdk.Coins{sdk.NewInt64Coin("uatom", 1)}, + DenomMetadata: []Metadata{ + { + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, + {"matom", uint32(3), []string{"milliatom"}}, + {"atom", uint32(6), nil}, + }, + Base: "uatom", + Display: "atom", + }, + }, }, - Base: "uatom", - Display: "atom", + false, }, + {"empty genesisState", GenesisState{}, false}, + { + "invalid params ", + GenesisState{ + Params: Params{ + SendEnabled: []*SendEnabled{ + {"", true}, + }, + }, + }, + true, + }, + { + "dup balances", + GenesisState{ + Balances: []Balance{ + { + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + Coins: sdk.Coins{sdk.NewInt64Coin("uatom", 1)}, + }, + { + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + Coins: sdk.Coins{sdk.NewInt64Coin("uatom", 1)}, + }, + }, + }, + true, + }, + { + "invalid balance", + GenesisState{ + Balances: []Balance{ + { + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + }, + }, + }, + true, + }, + { + "dup Metadata", + GenesisState{ + DenomMetadata: []Metadata{ + { + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, + {"matom", uint32(3), []string{"milliatom"}}, + {"atom", uint32(6), nil}, + }, + Base: "uatom", + Display: "atom", + }, + { + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, + {"matom", uint32(3), []string{"milliatom"}}, + {"atom", uint32(6), nil}, + }, + Base: "uatom", + Display: "atom", + }, + }, + }, + true, + }, + { + "invalid Metadata", + GenesisState{ + DenomMetadata: []Metadata{ + { + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, + {"matom", uint32(3), []string{"milliatom"}}, + {"atom", uint32(6), nil}, + }, + Base: "", + Display: "", + }, + }, + }, + true, + }, + { + "invalid supply", + GenesisState{ + Supply: sdk.Coins{sdk.Coin{Denom: "", Amount: sdk.OneInt()}}, + }, + true, }, - `[{"description":"The native staking token of the Cosmos Hub.","denom_units":[{"denom":"uatom","aliases":["microatom"]},{"denom":"matom","exponent":3,"aliases":["milliatom"]},{"denom":"atom","exponent":6}],"base":"uatom","display":"atom"}]`}, } for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { - bz, err := cdc.MarshalJSON(tc.input) - require.NoError(t, err) - require.Equal(t, tc.strOutput, string(bz)) - var newMetadata []types.Metadata - require.NoError(t, cdc.UnmarshalJSON(bz, &newMetadata)) + err := tc.genesisState.Validate() - if len(tc.input) == 0 { - require.Nil(t, newMetadata) + if tc.expErr { + require.Error(t, err) } else { - require.Equal(t, tc.input, newMetadata) + require.NoError(t, err) } }) } diff --git a/x/bank/types/metadata.go b/x/bank/types/metadata.go new file mode 100644 index 000000000000..5106964e994e --- /dev/null +++ b/x/bank/types/metadata.go @@ -0,0 +1,56 @@ +package types + +import ( + "fmt" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Validate performs a basic validation of the coin metadata fields +func (m Metadata) Validate() error { + if err := sdk.ValidateDenom(m.Base); err != nil { + return fmt.Errorf("invalid metadata base denom: %w", err) + } + + if err := sdk.ValidateDenom(m.Display); err != nil { + return fmt.Errorf("invalid metadata display denom: %w", err) + } + + seenUnits := make(map[string]bool) + for _, denomUnit := range m.DenomUnits { + if seenUnits[denomUnit.Denom] { + return fmt.Errorf("duplicate denomination unit %s", denomUnit.Denom) + } + + if err := denomUnit.Validate(); err != nil { + return err + } + + seenUnits[denomUnit.Denom] = true + } + + return nil +} + +// Validate performs a basic validation of the denomination unit fields +func (du DenomUnit) Validate() error { + if err := sdk.ValidateDenom(du.Denom); err != nil { + return fmt.Errorf("invalid denom unit: %w", err) + } + + seenAliases := make(map[string]bool) + for _, alias := range du.Aliases { + if seenAliases[alias] { + return fmt.Errorf("duplicate denomination unit alias %s", alias) + } + + if strings.TrimSpace(alias) == "" { + return fmt.Errorf("alias for denom unit %s cannot be blank", du.Denom) + } + + seenAliases[alias] = true + } + + return nil +} diff --git a/x/bank/types/metadata_test.go b/x/bank/types/metadata_test.go new file mode 100644 index 000000000000..29f4d220f95f --- /dev/null +++ b/x/bank/types/metadata_test.go @@ -0,0 +1,155 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +func TestMetadataValidate(t *testing.T) { + testCases := []struct { + name string + metadata types.Metadata + expErr bool + }{ + { + "non-empty coins", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, + {"matom", uint32(3), []string{"milliatom"}}, + {"atom", uint32(6), nil}, + }, + Base: "uatom", + Display: "atom", + }, + false, + }, + {"empty metadata", types.Metadata{}, true}, + { + "invalid base denom", + types.Metadata{ + Base: "", + }, + true, + }, + { + "invalid display denom", + types.Metadata{ + Base: "uatom", + Display: "", + }, + true, + }, + { + "duplicate denom unit", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, + {"uatom", uint32(0), []string{"microatom"}}, + }, + Base: "uatom", + Display: "atom", + }, + true, + }, + { + "invalid denom unit", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"", uint32(0), []string{"microatom"}}, + }, + Base: "uatom", + Display: "atom", + }, + true, + }, + { + "invalid denom unit alias", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"uatom", uint32(0), []string{""}}, + }, + Base: "uatom", + Display: "atom", + }, + true, + }, + { + "duplicate denom unit alias", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"uatom", uint32(0), []string{"microatom", "microatom"}}, + }, + Base: "uatom", + Display: "atom", + }, + true, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + + err := tc.metadata.Validate() + + if tc.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMarshalJSONMetaData(t *testing.T) { + cdc := codec.NewLegacyAmino() + + testCases := []struct { + name string + input []types.Metadata + strOutput string + }{ + {"nil metadata", nil, `null`}, + {"empty metadata", []types.Metadata{}, `[]`}, + {"non-empty coins", []types.Metadata{{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, // The default exponent value 0 is omitted in the json + {"matom", uint32(3), []string{"milliatom"}}, + {"atom", uint32(6), nil}, + }, + Base: "uatom", + Display: "atom", + }, + }, + `[{"description":"The native staking token of the Cosmos Hub.","denom_units":[{"denom":"uatom","aliases":["microatom"]},{"denom":"matom","exponent":3,"aliases":["milliatom"]},{"denom":"atom","exponent":6}],"base":"uatom","display":"atom"}]`}, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + bz, err := cdc.MarshalJSON(tc.input) + require.NoError(t, err) + require.Equal(t, tc.strOutput, string(bz)) + + var newMetadata []types.Metadata + require.NoError(t, cdc.UnmarshalJSON(bz, &newMetadata)) + + if len(tc.input) == 0 { + require.Nil(t, newMetadata) + } else { + require.Equal(t, tc.input, newMetadata) + } + }) + } +} diff --git a/x/bank/types/supply.go b/x/bank/types/supply.go index 558c852c2b83..c5c14b15bc2c 100644 --- a/x/bank/types/supply.go +++ b/x/bank/types/supply.go @@ -50,8 +50,8 @@ func (supply Supply) String() string { // ValidateBasic validates the Supply coins and returns error if invalid func (supply Supply) ValidateBasic() error { - if !supply.Total.IsValid() { - return fmt.Errorf("invalid total supply: %s", supply.Total.String()) + if err := supply.Total.Validate(); err != nil { + return fmt.Errorf("invalid total supply: %w", err) } return nil From bdd7fa9712cc47d41746877069d430a4704641ed Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Sun, 24 Jan 2021 11:33:27 -0300 Subject: [PATCH 073/152] simapp: increase supply balance when adding genaccount (#8418) * simapp: increase supply balance when adding genaccount * changelog --- CHANGELOG.md | 1 + simapp/simd/cmd/genaccounts.go | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96b8f5629e1b..f7bf603d7813 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes +* (simapp) [\#8418](https://github.com/cosmos/cosmos-sdk/pull/8418) Add balance coin to supply when adding a new genesis account * (x/bank) [\#8417](https://github.com/cosmos/cosmos-sdk/pull/8417) Validate balances and coin denom metadata on genesis * (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value diff --git a/simapp/simd/cmd/genaccounts.go b/simapp/simd/cmd/genaccounts.go index dc6925120e8d..57de144c36b4 100644 --- a/simapp/simd/cmd/genaccounts.go +++ b/simapp/simd/cmd/genaccounts.go @@ -151,6 +151,7 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa bankGenState := banktypes.GetGenesisStateFromAppState(depCdc, appState) bankGenState.Balances = append(bankGenState.Balances, balances) bankGenState.Balances = banktypes.SanitizeGenesisBalances(bankGenState.Balances) + bankGenState.Supply = bankGenState.Supply.Add(balances.Coins...) bankGenStateBz, err := cdc.MarshalJSON(bankGenState) if err != nil { From 56ed27ad9cf8e97853955cff371f33552e534a67 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Fri, 22 Jan 2021 10:37:21 -0500 Subject: [PATCH 074/152] use @aaronc's suggested proto upgrade method --- docs/core/proto-docs.md | 49 +++++++- proto/cosmos/gov/v1beta1/gov.proto | 10 +- proto/cosmos/gov/v1beta1/tx.proto | 8 +- x/gov/types/gov.pb.go | 192 ++++++++++++++--------------- x/gov/types/tx.pb.go | 10 +- 5 files changed, 155 insertions(+), 114 deletions(-) diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index d49cf8634bce..8c8dfc9c8233 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -249,6 +249,7 @@ - [TextProposal](#cosmos.gov.v1beta1.TextProposal) - [Vote](#cosmos.gov.v1beta1.Vote) - [VotingParams](#cosmos.gov.v1beta1.VotingParams) + - [WeightedVoteOption](#cosmos.gov.v1beta1.WeightedVoteOption) - [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) - [VoteOption](#cosmos.gov.v1beta1.VoteOption) @@ -283,6 +284,8 @@ - [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) - [MsgVote](#cosmos.gov.v1beta1.MsgVote) - [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) + - [MsgWeightedVote](#cosmos.gov.v1beta1.MsgWeightedVote) + - [MsgWeightedVoteResponse](#cosmos.gov.v1beta1.MsgWeightedVoteResponse) - [Msg](#cosmos.gov.v1beta1.Msg) @@ -3904,7 +3907,7 @@ A Vote consists of a proposal ID, the voter, and the vote option. | ----- | ---- | ----- | ----------- | | `proposal_id` | [uint64](#uint64) | | | | `voter` | [string](#string) | | | -| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | +| `options` | [WeightedVoteOption](#cosmos.gov.v1beta1.WeightedVoteOption) | repeated | | @@ -3925,6 +3928,22 @@ VotingParams defines the params for voting on governance proposals. + + + +### WeightedVoteOption +WeightedVoteOption defines a unit of vote for vote split. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | +| `weight` | [string](#string) | | | + + + + + @@ -4382,6 +4401,33 @@ MsgVoteResponse defines the Msg/Vote response type. + + + +### MsgWeightedVote +MsgVote defines a message to cast a vote. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | | +| `voter` | [string](#string) | | | +| `options` | [WeightedVoteOption](#cosmos.gov.v1beta1.WeightedVoteOption) | repeated | | + + + + + + + + +### MsgWeightedVoteResponse +MsgWeightedVoteResponse defines the MsgWeightedVote response type. + + + + + @@ -4398,6 +4444,7 @@ Msg defines the bank Msg service. | ----------- | ------------ | ------------- | ------------| ------- | -------- | | `SubmitProposal` | [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) | [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) | SubmitProposal defines a method to create new proposal given a content. | | | `Vote` | [MsgVote](#cosmos.gov.v1beta1.MsgVote) | [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) | Vote defines a method to add a vote on a specific proposal. | | +| `WeightedVote` | [MsgWeightedVote](#cosmos.gov.v1beta1.MsgWeightedVote) | [MsgWeightedVoteResponse](#cosmos.gov.v1beta1.MsgWeightedVoteResponse) | WeightedVote defines a method to add a weighted vote on a specific proposal. | | | `Deposit` | [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) | [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) | Deposit defines a method to add deposit on a specific proposal. | | diff --git a/proto/cosmos/gov/v1beta1/gov.proto b/proto/cosmos/gov/v1beta1/gov.proto index 25dd9a68cdb6..392534c535a1 100644 --- a/proto/cosmos/gov/v1beta1/gov.proto +++ b/proto/cosmos/gov/v1beta1/gov.proto @@ -32,7 +32,7 @@ enum VoteOption { // WeightedVoteOption defines a unit of vote for vote split. message WeightedVoteOption { VoteOption option = 1; - string weight = 2 [ + string weight = 2 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"weight\"" @@ -129,9 +129,11 @@ message Vote { option (gogoproto.goproto_stringer) = false; option (gogoproto.equal) = false; - uint64 proposal_id = 1 [(gogoproto.moretags) = "yaml:\"proposal_id\""]; - string voter = 2; - repeated WeightedVoteOption options = 3 [(gogoproto.nullable) = false]; + uint64 proposal_id = 1 [(gogoproto.moretags) = "yaml:\"proposal_id\""]; + string voter = 2; + reserved 3; + reserved "option"; + repeated WeightedVoteOption options = 4 [(gogoproto.nullable) = false]; } // DepositParams defines the params for deposits on governance proposals. diff --git a/proto/cosmos/gov/v1beta1/tx.proto b/proto/cosmos/gov/v1beta1/tx.proto index f5e1b5f1bf72..8635bf92c42a 100644 --- a/proto/cosmos/gov/v1beta1/tx.proto +++ b/proto/cosmos/gov/v1beta1/tx.proto @@ -60,14 +60,14 @@ message MsgVote { // MsgVote defines a message to cast a vote. message MsgWeightedVote { - option (gogoproto.equal) = false; + option (gogoproto.equal) = false; option (gogoproto.goproto_stringer) = false; option (gogoproto.stringer) = false; option (gogoproto.goproto_getters) = false; - uint64 proposal_id = 1 [(gogoproto.jsontag) = "proposal_id", (gogoproto.moretags) = "yaml:\"proposal_id\""]; - string voter = 2; - repeated WeightedVoteOption options = 3 [(gogoproto.nullable) = false]; + uint64 proposal_id = 1 [(gogoproto.jsontag) = "proposal_id", (gogoproto.moretags) = "yaml:\"proposal_id\""]; + string voter = 2; + repeated WeightedVoteOption options = 3 [(gogoproto.nullable) = false]; } // MsgVoteResponse defines the Msg/Vote response type. diff --git a/x/gov/types/gov.pb.go b/x/gov/types/gov.pb.go index d6548f70ce82..caa52a67a818 100644 --- a/x/gov/types/gov.pb.go +++ b/x/gov/types/gov.pb.go @@ -328,7 +328,7 @@ var xxx_messageInfo_TallyResult proto.InternalMessageInfo type Vote struct { ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty" yaml:"proposal_id"` Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` - Options []WeightedVoteOption `protobuf:"bytes,3,rep,name=options,proto3" json:"options"` + Options []WeightedVoteOption `protobuf:"bytes,4,rep,name=options,proto3" json:"options"` } func (m *Vote) Reset() { *m = Vote{} } @@ -503,97 +503,98 @@ func init() { func init() { proto.RegisterFile("cosmos/gov/v1beta1/gov.proto", fileDescriptor_6e82113c1a9a4b7c) } var fileDescriptor_6e82113c1a9a4b7c = []byte{ - // 1438 bytes of a gzipped FileDescriptorProto + // 1450 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0x51, 0x68, 0xdb, 0x56, - 0x17, 0xb6, 0x1c, 0xc7, 0x89, 0xaf, 0x9d, 0x44, 0xbd, 0x49, 0x13, 0xc7, 0x7f, 0x7f, 0xc9, 0xd3, - 0x46, 0x09, 0xa5, 0x75, 0xda, 0x6c, 0x6c, 0x2c, 0x85, 0x6d, 0x56, 0xac, 0xac, 0x1e, 0xc5, 0x36, - 0xb2, 0xea, 0xd0, 0xee, 0x41, 0x28, 0xf6, 0xad, 0xa3, 0xcd, 0xd2, 0xf5, 0xac, 0xeb, 0x34, 0x66, - 0x2f, 0x7b, 0x2c, 0x1e, 0x8c, 0x3e, 0x16, 0x86, 0xa1, 0x30, 0xc6, 0x60, 0xcf, 0x7b, 0xde, 0x73, - 0x18, 0x83, 0x95, 0x3d, 0x95, 0x0d, 0xdc, 0x35, 0x85, 0x51, 0xf2, 0x98, 0x87, 0x3d, 0x0f, 0xe9, - 0x5e, 0xc5, 0xb2, 0x1d, 0x96, 0x79, 0x4f, 0xd1, 0x3d, 0xf7, 0x7c, 0xdf, 0x77, 0xce, 0xf1, 0x39, - 0x47, 0x0a, 0xb8, 0x54, 0xc5, 0x8e, 0x85, 0x9d, 0xf5, 0x3a, 0xde, 0x5f, 0xdf, 0xbf, 0xb1, 0x8b, - 0x88, 0x71, 0xc3, 0x7d, 0xce, 0x34, 0x5b, 0x98, 0x60, 0x08, 0xe9, 0x6d, 0xc6, 0xb5, 0xb0, 0xdb, - 0x94, 0xc0, 0x10, 0xbb, 0x86, 0x83, 0x4e, 0x21, 0x55, 0x6c, 0xda, 0x14, 0x93, 0x5a, 0xaa, 0xe3, - 0x3a, 0xf6, 0x1e, 0xd7, 0xdd, 0x27, 0x66, 0x5d, 0xa5, 0x28, 0x9d, 0x5e, 0x30, 0x5a, 0x7a, 0x25, - 0xd6, 0x31, 0xae, 0x37, 0xd0, 0xba, 0x77, 0xda, 0x6d, 0xdf, 0x5f, 0x27, 0xa6, 0x85, 0x1c, 0x62, - 0x58, 0x4d, 0x1f, 0x3b, 0xea, 0x60, 0xd8, 0x1d, 0x76, 0x25, 0x8c, 0x5e, 0xd5, 0xda, 0x2d, 0x83, - 0x98, 0x98, 0x05, 0x23, 0x7d, 0xcb, 0x01, 0xb8, 0x83, 0xcc, 0xfa, 0x1e, 0x41, 0xb5, 0x0a, 0x26, - 0xa8, 0xd8, 0x74, 0x2f, 0xe1, 0xdb, 0x20, 0x8a, 0xbd, 0xa7, 0x24, 0x97, 0xe6, 0xd6, 0xe6, 0x37, - 0x84, 0xcc, 0x78, 0xa2, 0x99, 0x81, 0xbf, 0xca, 0xbc, 0xe1, 0x0e, 0x88, 0x3e, 0xf0, 0xd8, 0x92, - 0xe1, 0x34, 0xb7, 0x16, 0x93, 0xdf, 0x3f, 0xec, 0x8b, 0xa1, 0xdf, 0xfa, 0xe2, 0xe5, 0xba, 0x49, - 0xf6, 0xda, 0xbb, 0x99, 0x2a, 0xb6, 0x58, 0x6e, 0xec, 0xcf, 0x35, 0xa7, 0xf6, 0xe9, 0x3a, 0xe9, - 0x34, 0x91, 0x93, 0xc9, 0xa1, 0xea, 0x49, 0x5f, 0x9c, 0xeb, 0x18, 0x56, 0x63, 0x53, 0xa2, 0x2c, - 0x92, 0xca, 0xe8, 0xa4, 0x1d, 0x90, 0xd0, 0xd0, 0x01, 0x29, 0xb5, 0x70, 0x13, 0x3b, 0x46, 0x03, - 0x2e, 0x81, 0x69, 0x62, 0x92, 0x06, 0xf2, 0xe2, 0x8b, 0xa9, 0xf4, 0x00, 0xd3, 0x20, 0x5e, 0x43, - 0x4e, 0xb5, 0x65, 0xd2, 0xd8, 0xbd, 0x18, 0xd4, 0xa0, 0x69, 0x73, 0xe1, 0xd5, 0x13, 0x91, 0xfb, - 0xf5, 0x87, 0x6b, 0x33, 0x5b, 0xd8, 0x26, 0xc8, 0x26, 0xd2, 0x2f, 0x1c, 0x98, 0xc9, 0xa1, 0x26, - 0x76, 0x4c, 0x02, 0xdf, 0x01, 0xf1, 0x26, 0x13, 0xd0, 0xcd, 0x9a, 0x47, 0x1d, 0x91, 0x97, 0x4f, - 0xfa, 0x22, 0xa4, 0x41, 0x05, 0x2e, 0x25, 0x15, 0xf8, 0xa7, 0x7c, 0x0d, 0x5e, 0x02, 0xb1, 0x1a, - 0xe5, 0xc0, 0x2d, 0xa6, 0x3a, 0x30, 0xc0, 0x2a, 0x88, 0x1a, 0x16, 0x6e, 0xdb, 0x24, 0x39, 0x95, - 0x9e, 0x5a, 0x8b, 0x6f, 0xac, 0xfa, 0xc5, 0x74, 0x3b, 0xe4, 0xb4, 0x9a, 0x5b, 0xd8, 0xb4, 0xe5, - 0xeb, 0x6e, 0xbd, 0xbe, 0x7f, 0x2e, 0xae, 0xfd, 0x8b, 0x7a, 0xb9, 0x00, 0x47, 0x65, 0xd4, 0x9b, - 0xb3, 0x0f, 0x9f, 0x88, 0xa1, 0x57, 0x4f, 0xc4, 0x90, 0xf4, 0x57, 0x14, 0xcc, 0x9e, 0xd6, 0xe9, - 0xad, 0xb3, 0x52, 0x5a, 0x3c, 0xee, 0x8b, 0x61, 0xb3, 0x76, 0xd2, 0x17, 0x63, 0x34, 0xb1, 0xd1, - 0x7c, 0x6e, 0x82, 0x99, 0x2a, 0xad, 0x8f, 0x97, 0x4d, 0x7c, 0x63, 0x29, 0x43, 0xfb, 0x28, 0xe3, - 0xf7, 0x51, 0x26, 0x6b, 0x77, 0xe4, 0xf8, 0x4f, 0x83, 0x42, 0xaa, 0x3e, 0x02, 0x56, 0x40, 0xd4, - 0x21, 0x06, 0x69, 0x3b, 0xc9, 0x29, 0xaf, 0x77, 0xa4, 0xb3, 0x7a, 0xc7, 0x0f, 0xb0, 0xec, 0x79, - 0xca, 0xa9, 0x93, 0xbe, 0xb8, 0x3c, 0x52, 0x64, 0x4a, 0x22, 0xa9, 0x8c, 0x0d, 0x36, 0x01, 0xbc, - 0x6f, 0xda, 0x46, 0x43, 0x27, 0x46, 0xa3, 0xd1, 0xd1, 0x5b, 0xc8, 0x69, 0x37, 0x48, 0x32, 0xe2, - 0xc5, 0x27, 0x9e, 0xa5, 0xa1, 0xb9, 0x7e, 0xaa, 0xe7, 0x26, 0xbf, 0xe6, 0x16, 0xf6, 0xa4, 0x2f, - 0xae, 0x52, 0x91, 0x71, 0x22, 0x49, 0xe5, 0x3d, 0x63, 0x00, 0x04, 0x3f, 0x06, 0x71, 0xa7, 0xbd, - 0x6b, 0x99, 0x44, 0x77, 0x27, 0x2e, 0x39, 0xed, 0x49, 0xa5, 0xc6, 0x4a, 0xa1, 0xf9, 0xe3, 0x28, - 0x0b, 0x4c, 0x85, 0xf5, 0x4b, 0x00, 0x2c, 0x3d, 0x7a, 0x2e, 0x72, 0x2a, 0xa0, 0x16, 0x17, 0x00, - 0x4d, 0xc0, 0xb3, 0x16, 0xd1, 0x91, 0x5d, 0xa3, 0x0a, 0xd1, 0x73, 0x15, 0x5e, 0x67, 0x0a, 0x2b, - 0x54, 0x61, 0x94, 0x81, 0xca, 0xcc, 0x33, 0xb3, 0x62, 0xd7, 0x3c, 0xa9, 0x87, 0x1c, 0x98, 0x23, - 0x98, 0x18, 0x0d, 0x9d, 0x5d, 0x24, 0x67, 0xce, 0x6b, 0xc4, 0x5b, 0x4c, 0x67, 0x89, 0xea, 0x0c, - 0xa1, 0xa5, 0x89, 0x1a, 0x34, 0xe1, 0x61, 0xfd, 0x11, 0x6b, 0x80, 0x0b, 0xfb, 0x98, 0x98, 0x76, - 0xdd, 0xfd, 0x79, 0x5b, 0xac, 0xb0, 0xb3, 0xe7, 0xa6, 0xfd, 0x06, 0x0b, 0x27, 0x49, 0xc3, 0x19, - 0xa3, 0xa0, 0x79, 0x2f, 0x50, 0x7b, 0xd9, 0x35, 0x7b, 0x89, 0xdf, 0x07, 0xcc, 0x34, 0x28, 0x71, - 0xec, 0x5c, 0x2d, 0x89, 0x69, 0x2d, 0x0f, 0x69, 0x0d, 0x57, 0x78, 0x8e, 0x5a, 0x59, 0x81, 0x37, - 0x23, 0xee, 0x56, 0x91, 0x0e, 0xc3, 0x20, 0x1e, 0x6c, 0x9f, 0x0f, 0xc0, 0x54, 0x07, 0x39, 0x74, - 0x43, 0xc9, 0x99, 0x09, 0x36, 0x61, 0xde, 0x26, 0xaa, 0x0b, 0x85, 0xb7, 0xc0, 0x8c, 0xb1, 0xeb, - 0x10, 0xc3, 0x64, 0xbb, 0x6c, 0x62, 0x16, 0x1f, 0x0e, 0xdf, 0x03, 0x61, 0x1b, 0x7b, 0x03, 0x39, - 0x39, 0x49, 0xd8, 0xc6, 0xb0, 0x0e, 0x12, 0x36, 0xd6, 0x1f, 0x98, 0x64, 0x4f, 0xdf, 0x47, 0x04, - 0x7b, 0x63, 0x17, 0x93, 0x95, 0xc9, 0x98, 0x4e, 0xfa, 0xe2, 0x22, 0x2d, 0x6a, 0x90, 0x4b, 0x52, - 0x81, 0x8d, 0x77, 0x4c, 0xb2, 0x57, 0x41, 0x04, 0xb3, 0x52, 0x7e, 0xc7, 0x81, 0x88, 0xfb, 0x7a, - 0xf9, 0xef, 0x2b, 0x79, 0x09, 0x4c, 0xef, 0x63, 0x82, 0xfc, 0x75, 0x4c, 0x0f, 0x70, 0x1b, 0xcc, - 0xd0, 0x37, 0x95, 0xc3, 0x76, 0xf1, 0xe5, 0xb3, 0x16, 0xc7, 0xf8, 0x0b, 0x51, 0x8e, 0xb8, 0x99, - 0xaa, 0x3e, 0x78, 0x73, 0xf6, 0xb1, 0xbf, 0x6d, 0x7f, 0x0c, 0x83, 0x39, 0xd6, 0xdc, 0x25, 0xa3, - 0x65, 0x58, 0x0e, 0xfc, 0x9a, 0x03, 0x71, 0xcb, 0xb4, 0x4f, 0x67, 0x8d, 0x3b, 0x6f, 0xd6, 0x74, - 0x97, 0xfb, 0xb8, 0x2f, 0x5e, 0x0c, 0xa0, 0xae, 0x62, 0xcb, 0x24, 0xc8, 0x6a, 0x92, 0xce, 0x20, - 0xd7, 0xc0, 0xf5, 0x64, 0x23, 0x08, 0x2c, 0xd3, 0xf6, 0x07, 0xf0, 0x2b, 0x0e, 0x40, 0xcb, 0x38, - 0xf0, 0x89, 0xf4, 0x26, 0x6a, 0x99, 0xb8, 0xc6, 0xd6, 0xfc, 0xea, 0xd8, 0x58, 0xe4, 0xd8, 0xe7, - 0x02, 0xfd, 0xa9, 0x8f, 0xfb, 0xe2, 0xa5, 0x71, 0xf0, 0x50, 0xac, 0x6c, 0xc1, 0x8e, 0x7b, 0x49, - 0x8f, 0xdd, 0xc1, 0xe1, 0x2d, 0xe3, 0xc0, 0x2f, 0x17, 0x35, 0x7f, 0xc9, 0x81, 0x44, 0xc5, 0x9b, - 0x26, 0x56, 0xbf, 0xcf, 0x01, 0x9b, 0x2e, 0x3f, 0x36, 0xee, 0xbc, 0xd8, 0x6e, 0xb2, 0xd8, 0x56, - 0x86, 0x70, 0x43, 0x61, 0x2d, 0x0d, 0x0d, 0x73, 0x30, 0xa2, 0x04, 0xb5, 0xb1, 0x68, 0x7e, 0xf7, - 0x67, 0x98, 0x05, 0x73, 0x0f, 0x44, 0x3f, 0x6b, 0xe3, 0x56, 0xdb, 0xf2, 0xa2, 0x48, 0xc8, 0xf2, - 0x64, 0x1f, 0x34, 0xc7, 0x7d, 0x91, 0xa7, 0xf8, 0x41, 0x34, 0x2a, 0x63, 0x84, 0x55, 0x10, 0x23, - 0x7b, 0x2d, 0xe4, 0xec, 0xe1, 0x06, 0xfd, 0x01, 0x12, 0x13, 0x0d, 0x14, 0xa5, 0x5f, 0x3c, 0xa5, - 0x08, 0x28, 0x0c, 0x78, 0x61, 0x97, 0x03, 0xf3, 0xee, 0x94, 0xe9, 0x03, 0xa9, 0x29, 0x4f, 0xaa, - 0x3a, 0xb1, 0x54, 0x72, 0x98, 0x67, 0xa8, 0xbe, 0x17, 0x59, 0x7d, 0x87, 0x3c, 0x24, 0x75, 0xce, - 0x35, 0x68, 0xfe, 0xf9, 0xca, 0x9f, 0x1c, 0x00, 0x81, 0xaf, 0xcc, 0xab, 0x60, 0xa5, 0x52, 0xd4, - 0x14, 0xbd, 0x58, 0xd2, 0xf2, 0xc5, 0x82, 0x7e, 0xa7, 0x50, 0x2e, 0x29, 0x5b, 0xf9, 0xed, 0xbc, - 0x92, 0xe3, 0x43, 0xa9, 0x85, 0x6e, 0x2f, 0x1d, 0xa7, 0x8e, 0x8a, 0x2b, 0x02, 0x25, 0xb0, 0x10, - 0xf4, 0xbe, 0xab, 0x94, 0x79, 0x2e, 0x35, 0xd7, 0xed, 0xa5, 0x63, 0xd4, 0xeb, 0x2e, 0x72, 0xe0, - 0x15, 0xb0, 0x18, 0xf4, 0xc9, 0xca, 0x65, 0x2d, 0x9b, 0x2f, 0xf0, 0xe1, 0xd4, 0x85, 0x6e, 0x2f, - 0x3d, 0x47, 0xfd, 0xb2, 0x6c, 0x25, 0xa6, 0xc1, 0x7c, 0xd0, 0xb7, 0x50, 0xe4, 0xa7, 0x52, 0x89, - 0x6e, 0x2f, 0x3d, 0x4b, 0xdd, 0x0a, 0x18, 0x6e, 0x80, 0xe4, 0xb0, 0x87, 0xbe, 0x93, 0xd7, 0x6e, - 0xe9, 0x15, 0x45, 0x2b, 0xf2, 0x91, 0xd4, 0x52, 0xb7, 0x97, 0xe6, 0x7d, 0x5f, 0x7f, 0x7f, 0xa5, - 0x22, 0x0f, 0xbf, 0x11, 0x42, 0x57, 0x7e, 0x0e, 0x83, 0xf9, 0xe1, 0x4f, 0x1c, 0x98, 0x01, 0xff, - 0x2b, 0xa9, 0xc5, 0x52, 0xb1, 0x9c, 0xbd, 0xad, 0x97, 0xb5, 0xac, 0x76, 0xa7, 0x3c, 0x92, 0xb0, - 0x97, 0x0a, 0x75, 0x2e, 0x98, 0x0d, 0x78, 0x13, 0x08, 0xa3, 0xfe, 0x39, 0xa5, 0x54, 0x2c, 0xe7, - 0x35, 0xbd, 0xa4, 0xa8, 0xf9, 0x62, 0x8e, 0xe7, 0x52, 0x2b, 0xdd, 0x5e, 0x7a, 0x91, 0x42, 0x86, - 0x86, 0x0a, 0xbe, 0x0b, 0xfe, 0x3f, 0x0a, 0xae, 0x14, 0xb5, 0x7c, 0xe1, 0x43, 0x1f, 0x1b, 0x4e, - 0x2d, 0x77, 0x7b, 0x69, 0x48, 0xb1, 0x95, 0xc0, 0x04, 0xc0, 0xab, 0x60, 0x79, 0x14, 0x5a, 0xca, - 0x96, 0xcb, 0x4a, 0x8e, 0x9f, 0x4a, 0xf1, 0xdd, 0x5e, 0x3a, 0x41, 0x31, 0x25, 0xc3, 0x71, 0x50, - 0x0d, 0x5e, 0x07, 0xc9, 0x51, 0x6f, 0x55, 0xf9, 0x48, 0xd9, 0xd2, 0x94, 0x1c, 0x1f, 0x49, 0xc1, - 0x6e, 0x2f, 0x3d, 0x4f, 0xfd, 0x55, 0xf4, 0x09, 0xaa, 0x12, 0x74, 0x26, 0xff, 0x76, 0x36, 0x7f, - 0x5b, 0xc9, 0xf1, 0xd3, 0x41, 0xfe, 0x6d, 0xc3, 0x6c, 0xa0, 0x1a, 0x2d, 0xa7, 0x5c, 0x38, 0x7c, - 0x21, 0x84, 0x9e, 0xbd, 0x10, 0x42, 0x5f, 0x1c, 0x09, 0xa1, 0xc3, 0x23, 0x81, 0x7b, 0x7a, 0x24, - 0x70, 0x7f, 0x1c, 0x09, 0xdc, 0xa3, 0x97, 0x42, 0xe8, 0xe9, 0x4b, 0x21, 0xf4, 0xec, 0xa5, 0x10, - 0xba, 0xf7, 0xcf, 0x0b, 0xf1, 0xc0, 0xfb, 0x17, 0xce, 0xeb, 0xe7, 0xdd, 0xa8, 0xb7, 0x43, 0xde, - 0xfc, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x2e, 0xc3, 0x29, 0x39, 0xdd, 0x0d, 0x00, 0x00, + 0x17, 0xb6, 0x6c, 0xc7, 0x89, 0xaf, 0x9d, 0x44, 0xbd, 0x49, 0x13, 0xc7, 0x7f, 0x7f, 0xc9, 0xbf, + 0xfe, 0x51, 0x42, 0x69, 0x9d, 0x36, 0x1b, 0x1b, 0x4b, 0x61, 0x9b, 0x15, 0x2b, 0xab, 0x4b, 0xb1, + 0x8d, 0xac, 0x3a, 0xb4, 0x7b, 0x10, 0x8a, 0x7d, 0xeb, 0x68, 0xb3, 0x74, 0x3d, 0xeb, 0x3a, 0x4d, + 0xd8, 0xcb, 0x1e, 0x8b, 0x07, 0xa3, 0x8f, 0x85, 0x61, 0x28, 0x8c, 0xbd, 0xec, 0x79, 0x7b, 0xdd, + 0x73, 0x18, 0x83, 0x95, 0x3d, 0x95, 0x0d, 0xdc, 0x35, 0x85, 0x51, 0xf2, 0x98, 0x87, 0x3d, 0x0f, + 0xe9, 0x5e, 0xc5, 0xb2, 0x1d, 0x96, 0x79, 0x4f, 0xd1, 0x3d, 0xf7, 0x7c, 0xdf, 0x77, 0xce, 0xf1, + 0x39, 0x47, 0x0a, 0xb8, 0x54, 0xc3, 0x8e, 0x85, 0x9d, 0xb5, 0x06, 0xde, 0x5b, 0xdb, 0xbb, 0xb1, + 0x83, 0x88, 0x71, 0xc3, 0x7d, 0xce, 0xb6, 0xda, 0x98, 0x60, 0x08, 0xe9, 0x6d, 0xd6, 0xb5, 0xb0, + 0xdb, 0xb4, 0xc0, 0x10, 0x3b, 0x86, 0x83, 0x4e, 0x21, 0x35, 0x6c, 0xda, 0x14, 0x93, 0x5e, 0x6c, + 0xe0, 0x06, 0xf6, 0x1e, 0xd7, 0xdc, 0x27, 0x66, 0x5d, 0xa1, 0x28, 0x9d, 0x5e, 0x30, 0x5a, 0x7a, + 0x25, 0x36, 0x30, 0x6e, 0x34, 0xd1, 0x9a, 0x77, 0xda, 0xe9, 0x3c, 0x58, 0x23, 0xa6, 0x85, 0x1c, + 0x62, 0x58, 0x2d, 0x1f, 0x3b, 0xea, 0x60, 0xd8, 0x07, 0xec, 0x4a, 0x18, 0xbd, 0xaa, 0x77, 0xda, + 0x06, 0x31, 0x31, 0x0b, 0x46, 0xfa, 0x86, 0x03, 0x70, 0x1b, 0x99, 0x8d, 0x5d, 0x82, 0xea, 0x55, + 0x4c, 0x50, 0xa9, 0xe5, 0x5e, 0xc2, 0xb7, 0x41, 0x0c, 0x7b, 0x4f, 0x29, 0x2e, 0xc3, 0xad, 0xce, + 0xad, 0x0b, 0xd9, 0xf1, 0x44, 0xb3, 0x03, 0x7f, 0x95, 0x79, 0xc3, 0x6d, 0x10, 0x7b, 0xe8, 0xb1, + 0xa5, 0xc2, 0x19, 0x6e, 0x35, 0x2e, 0xbf, 0x7f, 0xd8, 0x17, 0x43, 0xbf, 0xf6, 0xc5, 0xcb, 0x0d, + 0x93, 0xec, 0x76, 0x76, 0xb2, 0x35, 0x6c, 0xb1, 0xdc, 0xd8, 0x9f, 0x6b, 0x4e, 0xfd, 0x93, 0x35, + 0x72, 0xd0, 0x42, 0x4e, 0x36, 0x8f, 0x6a, 0x27, 0x7d, 0x71, 0xf6, 0xc0, 0xb0, 0x9a, 0x1b, 0x12, + 0x65, 0x91, 0x54, 0x46, 0x27, 0x6d, 0x83, 0xa4, 0x86, 0xf6, 0x49, 0xb9, 0x8d, 0x5b, 0xd8, 0x31, + 0x9a, 0x70, 0x11, 0x4c, 0x11, 0x93, 0x34, 0x91, 0x17, 0x5f, 0x5c, 0xa5, 0x07, 0x98, 0x01, 0x89, + 0x3a, 0x72, 0x6a, 0x6d, 0x93, 0xc6, 0xee, 0xc5, 0xa0, 0x06, 0x4d, 0x1b, 0xf3, 0xaf, 0x9f, 0x8a, + 0xdc, 0x2f, 0xdf, 0x5d, 0x9b, 0xde, 0xc4, 0x36, 0x41, 0x36, 0x91, 0x7e, 0xe6, 0xc0, 0x74, 0x1e, + 0xb5, 0xb0, 0x63, 0x12, 0xf8, 0x0e, 0x48, 0xb4, 0x98, 0x80, 0x6e, 0xd6, 0x3d, 0xea, 0xa8, 0xbc, + 0x74, 0xd2, 0x17, 0x21, 0x0d, 0x2a, 0x70, 0x29, 0xa9, 0xc0, 0x3f, 0x15, 0xea, 0xf0, 0x12, 0x88, + 0xd7, 0x29, 0x07, 0x6e, 0x33, 0xd5, 0x81, 0x01, 0xd6, 0x40, 0xcc, 0xb0, 0x70, 0xc7, 0x26, 0xa9, + 0x48, 0x26, 0xb2, 0x9a, 0x58, 0x5f, 0xf1, 0x8b, 0xe9, 0x76, 0xc8, 0x69, 0x35, 0x37, 0xb1, 0x69, + 0xcb, 0xd7, 0xdd, 0x7a, 0x7d, 0xfb, 0x42, 0x5c, 0xfd, 0x07, 0xf5, 0x72, 0x01, 0x8e, 0xca, 0xa8, + 0x37, 0x66, 0x1e, 0x3d, 0x15, 0x43, 0xaf, 0x9f, 0x8a, 0x21, 0xe9, 0xcf, 0x18, 0x98, 0x39, 0xad, + 0xd3, 0x5b, 0x67, 0xa5, 0xb4, 0x70, 0xdc, 0x17, 0xc3, 0x66, 0xfd, 0xa4, 0x2f, 0xc6, 0x69, 0x62, + 0xa3, 0xf9, 0xdc, 0x04, 0xd3, 0x35, 0x5a, 0x1f, 0x2f, 0x9b, 0xc4, 0xfa, 0x62, 0x96, 0xf6, 0x51, + 0xd6, 0xef, 0xa3, 0x6c, 0xce, 0x3e, 0x90, 0x13, 0x3f, 0x0e, 0x0a, 0xa9, 0xfa, 0x08, 0x58, 0x05, + 0x31, 0x87, 0x18, 0xa4, 0xe3, 0xa4, 0x22, 0x5e, 0xef, 0x48, 0x67, 0xf5, 0x8e, 0x1f, 0x60, 0xc5, + 0xf3, 0x94, 0xd3, 0x27, 0x7d, 0x71, 0x69, 0xa4, 0xc8, 0x94, 0x44, 0x52, 0x19, 0x1b, 0x6c, 0x01, + 0xf8, 0xc0, 0xb4, 0x8d, 0xa6, 0x4e, 0x8c, 0x66, 0xf3, 0x40, 0x6f, 0x23, 0xa7, 0xd3, 0x24, 0xa9, + 0xa8, 0x17, 0x9f, 0x78, 0x96, 0x86, 0xe6, 0xfa, 0xa9, 0x9e, 0x9b, 0xfc, 0x3f, 0xb7, 0xb0, 0x27, + 0x7d, 0x71, 0x85, 0x8a, 0x8c, 0x13, 0x49, 0x2a, 0xef, 0x19, 0x03, 0x20, 0xf8, 0x11, 0x48, 0x38, + 0x9d, 0x1d, 0xcb, 0x24, 0xba, 0x3b, 0x71, 0xa9, 0x29, 0x4f, 0x2a, 0x3d, 0x56, 0x0a, 0xcd, 0x1f, + 0x47, 0x59, 0x60, 0x2a, 0xac, 0x5f, 0x02, 0x60, 0xe9, 0xf1, 0x0b, 0x91, 0x53, 0x01, 0xb5, 0xb8, + 0x00, 0x68, 0x02, 0x9e, 0xb5, 0x88, 0x8e, 0xec, 0x3a, 0x55, 0x88, 0x9d, 0xab, 0xf0, 0x7f, 0xa6, + 0xb0, 0x4c, 0x15, 0x46, 0x19, 0xa8, 0xcc, 0x1c, 0x33, 0x2b, 0x76, 0xdd, 0x93, 0x7a, 0xc4, 0x81, + 0x59, 0x82, 0x89, 0xd1, 0xd4, 0xd9, 0x45, 0x6a, 0xfa, 0xbc, 0x46, 0xbc, 0xc5, 0x74, 0x16, 0xa9, + 0xce, 0x10, 0x5a, 0x9a, 0xa8, 0x41, 0x93, 0x1e, 0xd6, 0x1f, 0xb1, 0x26, 0xb8, 0xb0, 0x87, 0x89, + 0x69, 0x37, 0xdc, 0x9f, 0xb7, 0xcd, 0x0a, 0x3b, 0x73, 0x6e, 0xda, 0x6f, 0xb0, 0x70, 0x52, 0x34, + 0x9c, 0x31, 0x0a, 0x9a, 0xf7, 0x3c, 0xb5, 0x57, 0x5c, 0xb3, 0x97, 0xf8, 0x03, 0xc0, 0x4c, 0x83, + 0x12, 0xc7, 0xcf, 0xd5, 0x92, 0x98, 0xd6, 0xd2, 0x90, 0xd6, 0x70, 0x85, 0x67, 0xa9, 0x95, 0x15, + 0x78, 0x23, 0xea, 0x6e, 0x15, 0xe9, 0x30, 0x0c, 0x12, 0xc1, 0xf6, 0xf9, 0x00, 0x44, 0x0e, 0x90, + 0x43, 0x37, 0x94, 0x9c, 0x9d, 0x60, 0x13, 0x16, 0x6c, 0xa2, 0xba, 0x50, 0x78, 0x0b, 0x4c, 0x1b, + 0x3b, 0x0e, 0x31, 0x4c, 0xb6, 0xcb, 0x26, 0x66, 0xf1, 0xe1, 0xf0, 0x3d, 0x10, 0xb6, 0xb1, 0x37, + 0x90, 0x93, 0x93, 0x84, 0x6d, 0x0c, 0x1b, 0x20, 0x69, 0x63, 0xfd, 0xa1, 0x49, 0x76, 0xf5, 0x3d, + 0x44, 0xb0, 0x37, 0x76, 0x71, 0x59, 0x99, 0x8c, 0xe9, 0xa4, 0x2f, 0x2e, 0xd0, 0xa2, 0x06, 0xb9, + 0x24, 0x15, 0xd8, 0x78, 0xdb, 0x24, 0xbb, 0x55, 0x44, 0x30, 0x2b, 0xe5, 0xf7, 0x1c, 0x88, 0xba, + 0xaf, 0x97, 0x7f, 0xbf, 0x92, 0x17, 0xc1, 0xd4, 0x1e, 0x26, 0xc8, 0x5f, 0xc7, 0xf4, 0x00, 0xb7, + 0xc0, 0x34, 0x7d, 0x53, 0x39, 0xa9, 0xa8, 0x37, 0x02, 0x97, 0xcf, 0x5a, 0x1c, 0xe3, 0x2f, 0x44, + 0x39, 0xea, 0x66, 0xaa, 0xfa, 0xe0, 0x8d, 0x99, 0x27, 0x6c, 0xdb, 0xde, 0x8e, 0xce, 0x44, 0xf8, + 0xa8, 0xff, 0xfe, 0x93, 0x7e, 0x08, 0x83, 0x59, 0xd6, 0xea, 0x65, 0xa3, 0x6d, 0x58, 0x0e, 0xfc, + 0x8a, 0x03, 0x09, 0xcb, 0xb4, 0x4f, 0x27, 0x8f, 0x3b, 0x6f, 0xf2, 0x74, 0x57, 0xe9, 0xb8, 0x2f, + 0x5e, 0x0c, 0xa0, 0xae, 0x62, 0xcb, 0x24, 0xc8, 0x6a, 0x91, 0x83, 0x41, 0xe6, 0x81, 0xeb, 0xc9, + 0x06, 0x12, 0x58, 0xa6, 0xed, 0x8f, 0xe3, 0x97, 0x1c, 0x80, 0x96, 0xb1, 0xef, 0x13, 0xe9, 0x2d, + 0xd4, 0x36, 0x71, 0x9d, 0x2d, 0xfd, 0x95, 0xb1, 0x21, 0xc9, 0xb3, 0x8f, 0x07, 0xfa, 0xc3, 0x1f, + 0xf7, 0xc5, 0x4b, 0xe3, 0xe0, 0xa1, 0x58, 0xd9, 0xba, 0x1d, 0xf7, 0x92, 0x9e, 0xb8, 0x63, 0xc4, + 0x5b, 0xc6, 0xbe, 0x5f, 0x2e, 0x6a, 0xfe, 0x82, 0x03, 0xc9, 0xaa, 0x37, 0x5b, 0xac, 0x7e, 0x9f, + 0x01, 0x36, 0x6b, 0x7e, 0x6c, 0xdc, 0x79, 0xb1, 0xdd, 0x64, 0xb1, 0x2d, 0x0f, 0xe1, 0x86, 0xc2, + 0x5a, 0x1c, 0x1a, 0xed, 0x60, 0x44, 0x49, 0x6a, 0x63, 0xd1, 0xfc, 0xe6, 0x4f, 0x34, 0x0b, 0xe6, + 0x3e, 0x88, 0x7d, 0xda, 0xc1, 0xed, 0x8e, 0xe5, 0x45, 0x91, 0x94, 0xe5, 0xc9, 0x3e, 0x6f, 0x8e, + 0xfb, 0x22, 0x4f, 0xf1, 0x83, 0x68, 0x54, 0xc6, 0x08, 0x6b, 0x20, 0x4e, 0x76, 0xdb, 0xc8, 0xd9, + 0xc5, 0x4d, 0xfa, 0x03, 0x24, 0x27, 0x1a, 0x2f, 0x4a, 0xbf, 0x70, 0x4a, 0x11, 0x50, 0x18, 0xf0, + 0xc2, 0x2e, 0x07, 0xe6, 0xdc, 0x99, 0xd3, 0x07, 0x52, 0x11, 0x4f, 0xaa, 0x36, 0xb1, 0x54, 0x6a, + 0x98, 0x67, 0xa8, 0xbe, 0x17, 0x59, 0x7d, 0x87, 0x3c, 0x24, 0x75, 0xd6, 0x35, 0x68, 0xfe, 0xf9, + 0xca, 0x1f, 0x1c, 0x00, 0x81, 0x6f, 0xce, 0xab, 0x60, 0xb9, 0x5a, 0xd2, 0x14, 0xbd, 0x54, 0xd6, + 0x0a, 0xa5, 0xa2, 0x7e, 0xb7, 0x58, 0x29, 0x2b, 0x9b, 0x85, 0xad, 0x82, 0x92, 0xe7, 0x43, 0xe9, + 0xf9, 0x6e, 0x2f, 0x93, 0xa0, 0x8e, 0x8a, 0x2b, 0x02, 0x25, 0x30, 0x1f, 0xf4, 0xbe, 0xa7, 0x54, + 0x78, 0x2e, 0x3d, 0xdb, 0xed, 0x65, 0xe2, 0xd4, 0xeb, 0x1e, 0x72, 0xe0, 0x15, 0xb0, 0x10, 0xf4, + 0xc9, 0xc9, 0x15, 0x2d, 0x57, 0x28, 0xf2, 0xe1, 0xf4, 0x85, 0x6e, 0x2f, 0x33, 0x4b, 0xfd, 0x72, + 0x6c, 0x41, 0x66, 0xc0, 0x5c, 0xd0, 0xb7, 0x58, 0xe2, 0x23, 0xe9, 0x64, 0xb7, 0x97, 0x99, 0xa1, + 0x6e, 0x45, 0x0c, 0xd7, 0x41, 0x6a, 0xd8, 0x43, 0xdf, 0x2e, 0x68, 0xb7, 0xf4, 0xaa, 0xa2, 0x95, + 0xf8, 0x68, 0x7a, 0xb1, 0xdb, 0xcb, 0xf0, 0xbe, 0xaf, 0xbf, 0xcd, 0xd2, 0xd1, 0x47, 0x5f, 0x0b, + 0xa1, 0x2b, 0x3f, 0x85, 0xc1, 0xdc, 0xf0, 0x07, 0x0f, 0xcc, 0x82, 0xff, 0x94, 0xd5, 0x52, 0xb9, + 0x54, 0xc9, 0xdd, 0xd1, 0x2b, 0x5a, 0x4e, 0xbb, 0x5b, 0x19, 0x49, 0xd8, 0x4b, 0x85, 0x3a, 0x17, + 0xcd, 0x26, 0xbc, 0x09, 0x84, 0x51, 0xff, 0xbc, 0x52, 0x2e, 0x55, 0x0a, 0x9a, 0x5e, 0x56, 0xd4, + 0x42, 0x29, 0xcf, 0x73, 0xe9, 0xe5, 0x6e, 0x2f, 0xb3, 0x40, 0x21, 0x43, 0x43, 0x05, 0xdf, 0x05, + 0xff, 0x1d, 0x05, 0x57, 0x4b, 0x5a, 0xa1, 0xf8, 0xa1, 0x8f, 0x0d, 0xa7, 0x97, 0xba, 0xbd, 0x0c, + 0xa4, 0xd8, 0x6a, 0x60, 0x02, 0xe0, 0x55, 0xb0, 0x34, 0x0a, 0x2d, 0xe7, 0x2a, 0x15, 0x25, 0xcf, + 0x47, 0xd2, 0x7c, 0xb7, 0x97, 0x49, 0x52, 0x4c, 0xd9, 0x70, 0x1c, 0x54, 0x87, 0xd7, 0x41, 0x6a, + 0xd4, 0x5b, 0x55, 0x6e, 0x2b, 0x9b, 0x9a, 0x92, 0xe7, 0xa3, 0x69, 0xd8, 0xed, 0x65, 0xe6, 0xa8, + 0xbf, 0x8a, 0x3e, 0x46, 0x35, 0x82, 0xce, 0xe4, 0xdf, 0xca, 0x15, 0xee, 0x28, 0x79, 0x7e, 0x2a, + 0xc8, 0xbf, 0x65, 0x98, 0x4d, 0x54, 0xa7, 0xe5, 0x94, 0x8b, 0x87, 0x2f, 0x85, 0xd0, 0xf3, 0x97, + 0x42, 0xe8, 0xf3, 0x23, 0x21, 0x74, 0x78, 0x24, 0x70, 0xcf, 0x8e, 0x04, 0xee, 0xf7, 0x23, 0x81, + 0x7b, 0xfc, 0x4a, 0x08, 0x3d, 0x7b, 0x25, 0x84, 0x9e, 0xbf, 0x12, 0x42, 0xf7, 0xff, 0x7e, 0x21, + 0xee, 0x7b, 0xff, 0xd0, 0x79, 0xfd, 0xbc, 0x13, 0xf3, 0x76, 0xc8, 0x9b, 0x7f, 0x05, 0x00, 0x00, + 0xff, 0xff, 0x51, 0x93, 0x54, 0x90, 0xeb, 0x0d, 0x00, 0x00, } func (this *TextProposal) Equal(that interface{}) bool { @@ -1028,7 +1029,7 @@ func (m *Vote) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintGov(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x1a + dAtA[i] = 0x22 } } if len(m.Voter) > 0 { @@ -1450,10 +1451,7 @@ func (m *WeightedVoteOption) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGov - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGov } if (iNdEx + skippy) > l { @@ -2306,7 +2304,7 @@ func (m *Vote) Unmarshal(dAtA []byte) error { } m.Voter = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 3: + case 4: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType) } diff --git a/x/gov/types/tx.pb.go b/x/gov/types/tx.pb.go index 93c4b63d7ace..24aac32f58c2 100644 --- a/x/gov/types/tx.pb.go +++ b/x/gov/types/tx.pb.go @@ -1493,10 +1493,7 @@ func (m *MsgWeightedVote) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { @@ -1596,10 +1593,7 @@ func (m *MsgWeightedVoteResponse) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } if (iNdEx + skippy) > l { From b125fccfd2e610c45531971b7a705396b427930a Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Sun, 24 Jan 2021 20:53:45 -0500 Subject: [PATCH 075/152] MsgWeightedVote -> MsgVoteWeighted --- docs/architecture/adr-037-gov-split-vote.md | 6 +- docs/core/proto-docs.md | 16 +- proto/cosmos/gov/v1beta1/tx.proto | 8 +- simapp/params/weights.go | 2 +- x/gov/client/cli/tx.go | 2 +- x/gov/client/rest/tx.go | 2 +- x/gov/client/utils/query.go | 10 +- x/gov/client/utils/query_test.go | 2 +- x/gov/handler.go | 4 +- x/gov/keeper/msg_server.go | 4 +- x/gov/simulation/operations.go | 24 +-- x/gov/simulation/operations_test.go | 12 +- x/gov/spec/04_events.md | 2 +- x/gov/types/codec.go | 4 +- x/gov/types/msgs.go | 22 +-- x/gov/types/msgs_test.go | 6 +- x/gov/types/tx.pb.go | 200 ++++++++++---------- 17 files changed, 163 insertions(+), 163 deletions(-) diff --git a/docs/architecture/adr-037-gov-split-vote.md b/docs/architecture/adr-037-gov-split-vote.md index af9cd8d6f6a9..ccc93e8bf245 100644 --- a/docs/architecture/adr-037-gov-split-vote.md +++ b/docs/architecture/adr-037-gov-split-vote.md @@ -35,7 +35,7 @@ type Vote struct { } ``` -And for backwards compatibility, we introduce `MsgWeightedVote` while keeping `MsgVote`. +And for backwards compatibility, we introduce `MsgVoteWeighted` while keeping `MsgVote`. ``` type MsgVote struct { ProposalID int64 @@ -43,14 +43,14 @@ type MsgVote struct { Option Option } -type MsgWeightedVote struct { +type MsgVoteWeighted struct { ProposalID int64 Voter sdk.Address Options []WeightedVoteOption } ``` -The `ValidateBasic` of a `MsgWeightedVote` struct would require that +The `ValidateBasic` of a `MsgVoteWeighted` struct would require that 1. The sum of all the Rates is equal to 1.0 2. No Option is repeated diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 8c8dfc9c8233..20acb644af47 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -284,8 +284,8 @@ - [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) - [MsgVote](#cosmos.gov.v1beta1.MsgVote) - [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) - - [MsgWeightedVote](#cosmos.gov.v1beta1.MsgWeightedVote) - - [MsgWeightedVoteResponse](#cosmos.gov.v1beta1.MsgWeightedVoteResponse) + - [MsgVoteWeighted](#cosmos.gov.v1beta1.MsgVoteWeighted) + - [MsgVoteWeightedResponse](#cosmos.gov.v1beta1.MsgVoteWeightedResponse) - [Msg](#cosmos.gov.v1beta1.Msg) @@ -4402,9 +4402,9 @@ MsgVoteResponse defines the Msg/Vote response type. - + -### MsgWeightedVote +### MsgVoteWeighted MsgVote defines a message to cast a vote. @@ -4419,10 +4419,10 @@ MsgVote defines a message to cast a vote. - + -### MsgWeightedVoteResponse -MsgWeightedVoteResponse defines the MsgWeightedVote response type. +### MsgVoteWeightedResponse +MsgVoteWeightedResponse defines the MsgVoteWeighted response type. @@ -4444,7 +4444,7 @@ Msg defines the bank Msg service. | ----------- | ------------ | ------------- | ------------| ------- | -------- | | `SubmitProposal` | [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) | [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) | SubmitProposal defines a method to create new proposal given a content. | | | `Vote` | [MsgVote](#cosmos.gov.v1beta1.MsgVote) | [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) | Vote defines a method to add a vote on a specific proposal. | | -| `WeightedVote` | [MsgWeightedVote](#cosmos.gov.v1beta1.MsgWeightedVote) | [MsgWeightedVoteResponse](#cosmos.gov.v1beta1.MsgWeightedVoteResponse) | WeightedVote defines a method to add a weighted vote on a specific proposal. | | +| `VoteWeighted` | [MsgVoteWeighted](#cosmos.gov.v1beta1.MsgVoteWeighted) | [MsgVoteWeightedResponse](#cosmos.gov.v1beta1.MsgVoteWeightedResponse) | WeightedVote defines a method to add a weighted vote on a specific proposal. | | | `Deposit` | [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) | [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) | Deposit defines a method to add deposit on a specific proposal. | | diff --git a/proto/cosmos/gov/v1beta1/tx.proto b/proto/cosmos/gov/v1beta1/tx.proto index 8635bf92c42a..25ae919370b0 100644 --- a/proto/cosmos/gov/v1beta1/tx.proto +++ b/proto/cosmos/gov/v1beta1/tx.proto @@ -18,7 +18,7 @@ service Msg { rpc Vote(MsgVote) returns (MsgVoteResponse); // WeightedVote defines a method to add a weighted vote on a specific proposal. - rpc WeightedVote(MsgWeightedVote) returns (MsgWeightedVoteResponse); + rpc VoteWeighted(MsgVoteWeighted) returns (MsgVoteWeightedResponse); // Deposit defines a method to add deposit on a specific proposal. rpc Deposit(MsgDeposit) returns (MsgDepositResponse); @@ -59,7 +59,7 @@ message MsgVote { } // MsgVote defines a message to cast a vote. -message MsgWeightedVote { +message MsgVoteWeighted { option (gogoproto.equal) = false; option (gogoproto.goproto_stringer) = false; option (gogoproto.stringer) = false; @@ -73,8 +73,8 @@ message MsgWeightedVote { // MsgVoteResponse defines the Msg/Vote response type. message MsgVoteResponse {} -// MsgWeightedVoteResponse defines the MsgWeightedVote response type. -message MsgWeightedVoteResponse {} +// MsgVoteWeightedResponse defines the MsgVoteWeighted response type. +message MsgVoteWeightedResponse {} // MsgDeposit defines a message to submit a deposit to an existing proposal. message MsgDeposit { diff --git a/simapp/params/weights.go b/simapp/params/weights.go index 1f4a25eba4aa..1581d2fc38bd 100644 --- a/simapp/params/weights.go +++ b/simapp/params/weights.go @@ -10,7 +10,7 @@ const ( DefaultWeightMsgFundCommunityPool int = 50 DefaultWeightMsgDeposit int = 100 DefaultWeightMsgVote int = 67 - DefaultWeightMsgWeightedVote int = 33 + DefaultWeightMsgVoteWeighted int = 33 DefaultWeightMsgUnjail int = 100 DefaultWeightMsgCreateValidator int = 100 DefaultWeightMsgEditValidator int = 5 diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 1d216265f458..6e1de14a077f 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -286,7 +286,7 @@ $ %s tx gov vote 1 yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05 --from mykey } // Build vote message and run basic validation - msg := types.NewMsgWeightedVote(from, proposalID, options) + msg := types.NewMsgVoteWeighted(from, proposalID, options) err = msg.ValidateBasic() if err != nil { return err diff --git a/x/gov/client/rest/tx.go b/x/gov/client/rest/tx.go index 41738269e485..b910cb7c84fb 100644 --- a/x/gov/client/rest/tx.go +++ b/x/gov/client/rest/tx.go @@ -159,7 +159,7 @@ func newWeightedVoteHandlerFn(clientCtx client.Context) http.HandlerFunc { } // create the message - msg := types.NewMsgWeightedVote(req.Voter, proposalID, options) + msg := types.NewMsgVoteWeighted(req.Voter, proposalID, options) if rest.CheckBadRequestError(w, msg.ValidateBasic()) { return } diff --git a/x/gov/client/utils/query.go b/x/gov/client/utils/query.go index 922da03f5640..5e4cead6cf6e 100644 --- a/x/gov/client/utils/query.go +++ b/x/gov/client/utils/query.go @@ -80,7 +80,7 @@ func QueryVotesByTxQuery(clientCtx client.Context, params types.QueryProposalVot var ( events = []string{ fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgVote), - fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgWeightedVote), + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgVoteWeighted), fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), } votes []types.Vote @@ -104,8 +104,8 @@ func QueryVotesByTxQuery(clientCtx client.Context, params types.QueryProposalVot ProposalId: params.ProposalID, Options: types.NewNonSplitVoteOption(voteMsg.Option), }) - } else if msg.Type() == types.TypeMsgWeightedVote { - voteMsg := msg.(*types.MsgWeightedVote) + } else if msg.Type() == types.TypeMsgVoteWeighted { + voteMsg := msg.(*types.MsgVoteWeighted) votes = append(votes, types.Vote{ Voter: voteMsg.Voter, @@ -166,8 +166,8 @@ func QueryVoteByTxQuery(clientCtx client.Context, params types.QueryVoteParams) } return bz, nil - } else if msg.Type() == types.TypeMsgWeightedVote { - voteMsg := msg.(*types.MsgWeightedVote) + } else if msg.Type() == types.TypeMsgVoteWeighted { + voteMsg := msg.(*types.MsgVoteWeighted) vote := types.Vote{ Voter: voteMsg.Voter, diff --git a/x/gov/client/utils/query_test.go b/x/gov/client/utils/query_test.go index da15c0ca92e3..4a68e05dfac5 100644 --- a/x/gov/client/utils/query_test.go +++ b/x/gov/client/utils/query_test.go @@ -75,7 +75,7 @@ func TestGetPaginatedVotes(t *testing.T) { } acc2Msgs := []sdk.Msg{ types.NewMsgVote(acc2, 0, types.OptionYes), - types.NewMsgWeightedVote(acc2, 0, types.NewNonSplitVoteOption(types.OptionYes)), + types.NewMsgVoteWeighted(acc2, 0, types.NewNonSplitVoteOption(types.OptionYes)), } for _, tc := range []testCase{ { diff --git a/x/gov/handler.go b/x/gov/handler.go index 61258e81396c..6af451d3dd31 100644 --- a/x/gov/handler.go +++ b/x/gov/handler.go @@ -27,8 +27,8 @@ func NewHandler(k keeper.Keeper) sdk.Handler { res, err := msgServer.Vote(sdk.WrapSDKContext(ctx), msg) return sdk.WrapServiceResult(ctx, res, err) - case *types.MsgWeightedVote: - res, err := msgServer.WeightedVote(sdk.WrapSDKContext(ctx), msg) + case *types.MsgVoteWeighted: + res, err := msgServer.VoteWeighted(sdk.WrapSDKContext(ctx), msg) return sdk.WrapServiceResult(ctx, res, err) default: diff --git a/x/gov/keeper/msg_server.go b/x/gov/keeper/msg_server.go index 438f380ed2ca..86e6e9326704 100644 --- a/x/gov/keeper/msg_server.go +++ b/x/gov/keeper/msg_server.go @@ -89,7 +89,7 @@ func (k msgServer) Vote(goCtx context.Context, msg *types.MsgVote) (*types.MsgVo return &types.MsgVoteResponse{}, nil } -func (k msgServer) WeightedVote(goCtx context.Context, msg *types.MsgWeightedVote) (*types.MsgWeightedVoteResponse, error) { +func (k msgServer) VoteWeighted(goCtx context.Context, msg *types.MsgVoteWeighted) (*types.MsgVoteWeightedResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) accAddr, accErr := sdk.AccAddressFromBech32(msg.Voter) if accErr != nil { @@ -116,7 +116,7 @@ func (k msgServer) WeightedVote(goCtx context.Context, msg *types.MsgWeightedVot ), ) - return &types.MsgWeightedVoteResponse{}, nil + return &types.MsgVoteWeightedResponse{}, nil } func (k msgServer) Deposit(goCtx context.Context, msg *types.MsgDeposit) (*types.MsgDepositResponse, error) { diff --git a/x/gov/simulation/operations.go b/x/gov/simulation/operations.go index 9e3dcae964a6..e25d87c7ccc8 100644 --- a/x/gov/simulation/operations.go +++ b/x/gov/simulation/operations.go @@ -22,7 +22,7 @@ var initialProposalID = uint64(100000000000000) const ( OpWeightMsgDeposit = "op_weight_msg_deposit" OpWeightMsgVote = "op_weight_msg_vote" - OpWeightMsgWeightedVote = "op_weight_msg_weighted_vote" + OpWeightMsgVoteWeighted = "op_weight_msg_weighted_vote" ) // WeightedOperations returns all the operations from the module with their respective weights @@ -34,7 +34,7 @@ func WeightedOperations( var ( weightMsgDeposit int weightMsgVote int - weightMsgWeightedVote int + weightMsgVoteWeighted int ) appParams.GetOrGenerate(cdc, OpWeightMsgDeposit, &weightMsgDeposit, nil, @@ -49,9 +49,9 @@ func WeightedOperations( }, ) - appParams.GetOrGenerate(cdc, OpWeightMsgWeightedVote, &weightMsgWeightedVote, nil, + appParams.GetOrGenerate(cdc, OpWeightMsgVoteWeighted, &weightMsgVoteWeighted, nil, func(_ *rand.Rand) { - weightMsgWeightedVote = simappparams.DefaultWeightMsgWeightedVote + weightMsgVoteWeighted = simappparams.DefaultWeightMsgVoteWeighted }, ) @@ -83,8 +83,8 @@ func WeightedOperations( SimulateMsgVote(ak, bk, k), ), simulation.NewWeightedOperation( - weightMsgWeightedVote, - SimulateMsgWeightedVote(ak, bk, k), + weightMsgVoteWeighted, + SimulateMsgVoteWeighted(ak, bk, k), ), } @@ -327,12 +327,12 @@ func operationSimulateMsgVote(ak types.AccountKeeper, bk types.BankKeeper, k kee } } -// SimulateMsgWeightedVote generates a MsgWeightedVote with random values. -func SimulateMsgWeightedVote(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { - return operationSimulateMsgWeightedVote(ak, bk, k, simtypes.Account{}, -1) +// SimulateMsgVoteWeighted generates a MsgVoteWeighted with random values. +func SimulateMsgVoteWeighted(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { + return operationSimulateMsgVoteWeighted(ak, bk, k, simtypes.Account{}, -1) } -func operationSimulateMsgWeightedVote(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, +func operationSimulateMsgVoteWeighted(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, simAccount simtypes.Account, proposalIDInt int64) simtypes.Operation { return func( r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, @@ -349,14 +349,14 @@ func operationSimulateMsgWeightedVote(ak types.AccountKeeper, bk types.BankKeepe var ok bool proposalID, ok = randomProposalID(r, k, ctx, types.StatusVotingPeriod) if !ok { - return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgWeightedVote, "unable to generate proposalID"), nil, nil + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgVoteWeighted, "unable to generate proposalID"), nil, nil } default: proposalID = uint64(proposalIDInt) } options := randomWeightedVotingOptions(r) - msg := types.NewMsgWeightedVote(simAccount.Address, proposalID, options) + msg := types.NewMsgVoteWeighted(simAccount.Address, proposalID, options) account := ak.GetAccount(ctx, simAccount.Address) spendable := bk.SpendableCoins(ctx, account.GetAddress()) diff --git a/x/gov/simulation/operations_test.go b/x/gov/simulation/operations_test.go index 52217ad74fc4..8d1076fffd6d 100644 --- a/x/gov/simulation/operations_test.go +++ b/x/gov/simulation/operations_test.go @@ -80,7 +80,7 @@ func TestWeightedOperations(t *testing.T) { {2, types.ModuleName, "submit_proposal"}, {simappparams.DefaultWeightMsgDeposit, types.ModuleName, types.TypeMsgDeposit}, {simappparams.DefaultWeightMsgVote, types.ModuleName, types.TypeMsgVote}, - {simappparams.DefaultWeightMsgWeightedVote, types.ModuleName, types.TypeMsgWeightedVote}, + {simappparams.DefaultWeightMsgVoteWeighted, types.ModuleName, types.TypeMsgVoteWeighted}, } for i, w := range weightesOps { @@ -208,9 +208,9 @@ func TestSimulateMsgVote(t *testing.T) { require.Equal(t, types.TypeMsgVote, msg.Type()) } -// TestSimulateMsgWeightedVote tests the normal scenario of a valid message of type TypeMsgWeightedVote. +// TestSimulateMsgVoteWeighted tests the normal scenario of a valid message of type TypeMsgVoteWeighted. // Abonormal scenarios, where the message is created by an errors are not tested here. -func TestSimulateMsgWeightedVote(t *testing.T) { +func TestSimulateMsgVoteWeighted(t *testing.T) { app, ctx := createTestApp(false) blockTime := time.Now().UTC() ctx = ctx.WithBlockTime(blockTime) @@ -235,11 +235,11 @@ func TestSimulateMsgWeightedVote(t *testing.T) { app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: app.LastBlockHeight() + 1, AppHash: app.LastCommitID().Hash, Time: blockTime}}) // execute operation - op := simulation.SimulateMsgWeightedVote(app.AccountKeeper, app.BankKeeper, app.GovKeeper) + op := simulation.SimulateMsgVoteWeighted(app.AccountKeeper, app.BankKeeper, app.GovKeeper) operationMsg, _, err := op(r, app.BaseApp, ctx, accounts, "") require.NoError(t, err) - var msg types.MsgWeightedVote + var msg types.MsgVoteWeighted types.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) require.True(t, operationMsg.OK) @@ -247,7 +247,7 @@ func TestSimulateMsgWeightedVote(t *testing.T) { require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Voter) require.True(t, len(msg.Options) >= 1) require.Equal(t, "gov", msg.Route()) - require.Equal(t, types.TypeMsgWeightedVote, msg.Type()) + require.Equal(t, types.TypeMsgVoteWeighted, msg.Type()) } // returns context and an app with updated mint keeper diff --git a/x/gov/spec/04_events.md b/x/gov/spec/04_events.md index 1ea2a36b7613..300d4d187c80 100644 --- a/x/gov/spec/04_events.md +++ b/x/gov/spec/04_events.md @@ -41,7 +41,7 @@ The governance module emits the following events: | message | action | vote | | message | sender | {senderAddress} | -### MsgWeightedVote +### MsgVoteWeighted | Type | Attribute Key | Attribute Value | | ------------- | ------------- | ------------------------ | diff --git a/x/gov/types/codec.go b/x/gov/types/codec.go index 92d25f2ca159..e59e0ef49c66 100644 --- a/x/gov/types/codec.go +++ b/x/gov/types/codec.go @@ -15,7 +15,7 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgSubmitProposal{}, "cosmos-sdk/MsgSubmitProposal", nil) cdc.RegisterConcrete(&MsgDeposit{}, "cosmos-sdk/MsgDeposit", nil) cdc.RegisterConcrete(&MsgVote{}, "cosmos-sdk/MsgVote", nil) - cdc.RegisterConcrete(&MsgWeightedVote{}, "cosmos-sdk/MsgWeightedVote", nil) + cdc.RegisterConcrete(&MsgVoteWeighted{}, "cosmos-sdk/MsgVoteWeighted", nil) cdc.RegisterConcrete(&TextProposal{}, "cosmos-sdk/TextProposal", nil) } @@ -23,7 +23,7 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), &MsgSubmitProposal{}, &MsgVote{}, - &MsgWeightedVote{}, + &MsgVoteWeighted{}, &MsgDeposit{}, ) registry.RegisterInterface( diff --git a/x/gov/types/msgs.go b/x/gov/types/msgs.go index 4c8d47d7c0f0..157c088d5846 100644 --- a/x/gov/types/msgs.go +++ b/x/gov/types/msgs.go @@ -16,12 +16,12 @@ import ( const ( TypeMsgDeposit = "deposit" TypeMsgVote = "vote" - TypeMsgWeightedVote = "weighted_vote" + TypeMsgVoteWeighted = "weighted_vote" TypeMsgSubmitProposal = "submit_proposal" ) var ( - _, _, _, _ sdk.Msg = &MsgSubmitProposal{}, &MsgDeposit{}, &MsgVote{}, &MsgWeightedVote{} + _, _, _, _ sdk.Msg = &MsgSubmitProposal{}, &MsgDeposit{}, &MsgVote{}, &MsgVoteWeighted{} _ types.UnpackInterfacesMessage = &MsgSubmitProposal{} ) @@ -219,20 +219,20 @@ func (msg MsgVote) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{voter} } -// NewMsgWeightedVote creates a message to cast a vote on an active proposal +// NewMsgVoteWeighted creates a message to cast a vote on an active proposal //nolint:interfacer -func NewMsgWeightedVote(voter sdk.AccAddress, proposalID uint64, options WeightedVoteOptions) *MsgWeightedVote { - return &MsgWeightedVote{proposalID, voter.String(), options} +func NewMsgVoteWeighted(voter sdk.AccAddress, proposalID uint64, options WeightedVoteOptions) *MsgVoteWeighted { + return &MsgVoteWeighted{proposalID, voter.String(), options} } // Route implements Msg -func (msg MsgWeightedVote) Route() string { return RouterKey } +func (msg MsgVoteWeighted) Route() string { return RouterKey } // Type implements Msg -func (msg MsgWeightedVote) Type() string { return TypeMsgWeightedVote } +func (msg MsgVoteWeighted) Type() string { return TypeMsgVoteWeighted } // ValidateBasic implements Msg -func (msg MsgWeightedVote) ValidateBasic() error { +func (msg MsgVoteWeighted) ValidateBasic() error { if msg.Voter == "" { return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Voter) } @@ -262,19 +262,19 @@ func (msg MsgWeightedVote) ValidateBasic() error { } // String implements the Stringer interface -func (msg MsgWeightedVote) String() string { +func (msg MsgVoteWeighted) String() string { out, _ := yaml.Marshal(msg) return string(out) } // GetSignBytes implements Msg -func (msg MsgWeightedVote) GetSignBytes() []byte { +func (msg MsgVoteWeighted) GetSignBytes() []byte { bz := ModuleCdc.MustMarshalJSON(&msg) return sdk.MustSortJSON(bz) } // GetSigners implements Msg -func (msg MsgWeightedVote) GetSigners() []sdk.AccAddress { +func (msg MsgVoteWeighted) GetSigners() []sdk.AccAddress { voter, _ := sdk.AccAddressFromBech32(msg.Voter) return []sdk.AccAddress{voter} } diff --git a/x/gov/types/msgs_test.go b/x/gov/types/msgs_test.go index a1e1accba022..b942b898646d 100644 --- a/x/gov/types/msgs_test.go +++ b/x/gov/types/msgs_test.go @@ -118,8 +118,8 @@ func TestMsgVote(t *testing.T) { } } -// test ValidateBasic for MsgWeightedVote -func TestMsgWeightedVote(t *testing.T) { +// test ValidateBasic for MsgVoteWeighted +func TestMsgVoteWeighted(t *testing.T) { tests := []struct { proposalID uint64 voterAddr sdk.AccAddress @@ -150,7 +150,7 @@ func TestMsgWeightedVote(t *testing.T) { } for i, tc := range tests { - msg := NewMsgWeightedVote(tc.voterAddr, tc.proposalID, tc.options) + msg := NewMsgVoteWeighted(tc.voterAddr, tc.proposalID, tc.options) if tc.expectPass { require.Nil(t, msg.ValidateBasic(), "test: %v", i) } else { diff --git a/x/gov/types/tx.pb.go b/x/gov/types/tx.pb.go index 24aac32f58c2..851f2b622fde 100644 --- a/x/gov/types/tx.pb.go +++ b/x/gov/types/tx.pb.go @@ -157,23 +157,23 @@ func (m *MsgVote) XXX_DiscardUnknown() { var xxx_messageInfo_MsgVote proto.InternalMessageInfo // MsgVote defines a message to cast a vote. -type MsgWeightedVote struct { +type MsgVoteWeighted struct { ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id" yaml:"proposal_id"` Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` Options []WeightedVoteOption `protobuf:"bytes,3,rep,name=options,proto3" json:"options"` } -func (m *MsgWeightedVote) Reset() { *m = MsgWeightedVote{} } -func (*MsgWeightedVote) ProtoMessage() {} -func (*MsgWeightedVote) Descriptor() ([]byte, []int) { +func (m *MsgVoteWeighted) Reset() { *m = MsgVoteWeighted{} } +func (*MsgVoteWeighted) ProtoMessage() {} +func (*MsgVoteWeighted) Descriptor() ([]byte, []int) { return fileDescriptor_3c053992595e3dce, []int{3} } -func (m *MsgWeightedVote) XXX_Unmarshal(b []byte) error { +func (m *MsgVoteWeighted) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *MsgWeightedVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *MsgVoteWeighted) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_MsgWeightedVote.Marshal(b, m, deterministic) + return xxx_messageInfo_MsgVoteWeighted.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -183,17 +183,17 @@ func (m *MsgWeightedVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, err return b[:n], nil } } -func (m *MsgWeightedVote) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgWeightedVote.Merge(m, src) +func (m *MsgVoteWeighted) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVoteWeighted.Merge(m, src) } -func (m *MsgWeightedVote) XXX_Size() int { +func (m *MsgVoteWeighted) XXX_Size() int { return m.Size() } -func (m *MsgWeightedVote) XXX_DiscardUnknown() { - xxx_messageInfo_MsgWeightedVote.DiscardUnknown(m) +func (m *MsgVoteWeighted) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVoteWeighted.DiscardUnknown(m) } -var xxx_messageInfo_MsgWeightedVote proto.InternalMessageInfo +var xxx_messageInfo_MsgVoteWeighted proto.InternalMessageInfo // MsgVoteResponse defines the Msg/Vote response type. type MsgVoteResponse struct { @@ -232,22 +232,22 @@ func (m *MsgVoteResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgVoteResponse proto.InternalMessageInfo -// MsgWeightedVoteResponse defines the MsgWeightedVote response type. -type MsgWeightedVoteResponse struct { +// MsgVoteWeightedResponse defines the MsgVoteWeighted response type. +type MsgVoteWeightedResponse struct { } -func (m *MsgWeightedVoteResponse) Reset() { *m = MsgWeightedVoteResponse{} } -func (m *MsgWeightedVoteResponse) String() string { return proto.CompactTextString(m) } -func (*MsgWeightedVoteResponse) ProtoMessage() {} -func (*MsgWeightedVoteResponse) Descriptor() ([]byte, []int) { +func (m *MsgVoteWeightedResponse) Reset() { *m = MsgVoteWeightedResponse{} } +func (m *MsgVoteWeightedResponse) String() string { return proto.CompactTextString(m) } +func (*MsgVoteWeightedResponse) ProtoMessage() {} +func (*MsgVoteWeightedResponse) Descriptor() ([]byte, []int) { return fileDescriptor_3c053992595e3dce, []int{5} } -func (m *MsgWeightedVoteResponse) XXX_Unmarshal(b []byte) error { +func (m *MsgVoteWeightedResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *MsgWeightedVoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *MsgVoteWeightedResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_MsgWeightedVoteResponse.Marshal(b, m, deterministic) + return xxx_messageInfo_MsgVoteWeightedResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -257,17 +257,17 @@ func (m *MsgWeightedVoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]b return b[:n], nil } } -func (m *MsgWeightedVoteResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgWeightedVoteResponse.Merge(m, src) +func (m *MsgVoteWeightedResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVoteWeightedResponse.Merge(m, src) } -func (m *MsgWeightedVoteResponse) XXX_Size() int { +func (m *MsgVoteWeightedResponse) XXX_Size() int { return m.Size() } -func (m *MsgWeightedVoteResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgWeightedVoteResponse.DiscardUnknown(m) +func (m *MsgVoteWeightedResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVoteWeightedResponse.DiscardUnknown(m) } -var xxx_messageInfo_MsgWeightedVoteResponse proto.InternalMessageInfo +var xxx_messageInfo_MsgVoteWeightedResponse proto.InternalMessageInfo // MsgDeposit defines a message to submit a deposit to an existing proposal. type MsgDeposit struct { @@ -349,9 +349,9 @@ func init() { proto.RegisterType((*MsgSubmitProposal)(nil), "cosmos.gov.v1beta1.MsgSubmitProposal") proto.RegisterType((*MsgSubmitProposalResponse)(nil), "cosmos.gov.v1beta1.MsgSubmitProposalResponse") proto.RegisterType((*MsgVote)(nil), "cosmos.gov.v1beta1.MsgVote") - proto.RegisterType((*MsgWeightedVote)(nil), "cosmos.gov.v1beta1.MsgWeightedVote") + proto.RegisterType((*MsgVoteWeighted)(nil), "cosmos.gov.v1beta1.MsgVoteWeighted") proto.RegisterType((*MsgVoteResponse)(nil), "cosmos.gov.v1beta1.MsgVoteResponse") - proto.RegisterType((*MsgWeightedVoteResponse)(nil), "cosmos.gov.v1beta1.MsgWeightedVoteResponse") + proto.RegisterType((*MsgVoteWeightedResponse)(nil), "cosmos.gov.v1beta1.MsgVoteWeightedResponse") proto.RegisterType((*MsgDeposit)(nil), "cosmos.gov.v1beta1.MsgDeposit") proto.RegisterType((*MsgDepositResponse)(nil), "cosmos.gov.v1beta1.MsgDepositResponse") } @@ -359,48 +359,48 @@ func init() { func init() { proto.RegisterFile("cosmos/gov/v1beta1/tx.proto", fileDescriptor_3c053992595e3dce) } var fileDescriptor_3c053992595e3dce = []byte{ - // 655 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0xc1, 0x6b, 0x13, 0x4f, - 0x14, 0xde, 0x4d, 0xfa, 0x6b, 0x7e, 0x7d, 0x91, 0xd6, 0x2e, 0x41, 0x93, 0x6d, 0xd9, 0x0d, 0x2b, - 0x2d, 0x01, 0xe9, 0xae, 0x8d, 0xe0, 0xa1, 0x9e, 0x4c, 0xa5, 0xa8, 0x10, 0xd4, 0x15, 0x14, 0xbc, - 0xd4, 0x4d, 0xb2, 0x9d, 0x2e, 0x26, 0xfb, 0x96, 0xcc, 0x24, 0x34, 0x37, 0x8f, 0x9e, 0xd4, 0xa3, - 0xc7, 0x9e, 0xbd, 0x09, 0xfe, 0x11, 0xd5, 0x53, 0x8f, 0x1e, 0x24, 0x4a, 0x7b, 0x51, 0xf1, 0xd4, - 0xbf, 0x40, 0x76, 0x66, 0x36, 0x8d, 0x6d, 0x12, 0x2a, 0x14, 0x4f, 0xc9, 0x7b, 0xdf, 0xfb, 0xbe, - 0xbc, 0xef, 0xcd, 0x9b, 0x09, 0x2c, 0xd4, 0x91, 0xb6, 0x90, 0x3a, 0x04, 0xbb, 0x4e, 0x77, 0xb5, - 0xe6, 0x33, 0x6f, 0xd5, 0x61, 0x3b, 0x76, 0xd4, 0x46, 0x86, 0x9a, 0x26, 0x40, 0x9b, 0x60, 0xd7, - 0x96, 0xa0, 0x6e, 0x48, 0x42, 0xcd, 0xa3, 0xfe, 0x80, 0x51, 0xc7, 0x20, 0x14, 0x1c, 0x7d, 0x71, - 0x84, 0x60, 0xcc, 0x17, 0x68, 0x41, 0xa0, 0x9b, 0x3c, 0x72, 0xa4, 0xbc, 0x80, 0x72, 0x04, 0x09, - 0x8a, 0x7c, 0xfc, 0x2d, 0x21, 0x10, 0x44, 0xd2, 0xf4, 0x1d, 0x1e, 0xd5, 0x3a, 0x5b, 0x8e, 0x17, - 0xf6, 0x04, 0x64, 0xbd, 0x4e, 0xc1, 0x7c, 0x95, 0x92, 0x47, 0x9d, 0x5a, 0x2b, 0x60, 0x0f, 0xda, - 0x18, 0x21, 0xf5, 0x9a, 0xda, 0x4d, 0xc8, 0xd4, 0x31, 0x64, 0x7e, 0xc8, 0xf2, 0x6a, 0x51, 0x2d, - 0x65, 0xcb, 0x39, 0x5b, 0x48, 0xd8, 0x89, 0x84, 0x7d, 0x2b, 0xec, 0x55, 0xb2, 0x9f, 0x3e, 0xac, - 0x64, 0xd6, 0x45, 0xa1, 0x9b, 0x30, 0xb4, 0x57, 0x2a, 0xcc, 0x05, 0x61, 0xc0, 0x02, 0xaf, 0xb9, - 0xd9, 0xf0, 0x23, 0xa4, 0x01, 0xcb, 0xa7, 0x8a, 0xe9, 0x52, 0xb6, 0x5c, 0xb0, 0x65, 0xb3, 0xb1, - 0xef, 0x64, 0x18, 0xf6, 0x3a, 0x06, 0x61, 0xe5, 0xde, 0x5e, 0xdf, 0x54, 0x8e, 0xfa, 0xe6, 0xa5, - 0x9e, 0xd7, 0x6a, 0xae, 0x59, 0x27, 0xf8, 0xd6, 0xbb, 0xaf, 0x66, 0x89, 0x04, 0x6c, 0xbb, 0x53, - 0xb3, 0xeb, 0xd8, 0x92, 0x9e, 0xe5, 0xc7, 0x0a, 0x6d, 0x3c, 0x77, 0x58, 0x2f, 0xf2, 0x29, 0x97, - 0xa2, 0xee, 0xac, 0x64, 0xdf, 0x16, 0x64, 0x4d, 0x87, 0xff, 0x23, 0xee, 0xcc, 0x6f, 0xe7, 0xd3, - 0x45, 0xb5, 0x34, 0xe3, 0x0e, 0xe2, 0xb5, 0x8b, 0x2f, 0x77, 0x4d, 0xe5, 0xed, 0xae, 0xa9, 0x7c, - 0xdf, 0x35, 0x95, 0x17, 0x5f, 0x8a, 0x8a, 0x55, 0x87, 0xc2, 0xa9, 0x81, 0xb8, 0x3e, 0x8d, 0x30, - 0xa4, 0xbe, 0xb6, 0x01, 0xd9, 0x48, 0xe6, 0x36, 0x83, 0x06, 0x1f, 0xce, 0x54, 0x65, 0xe9, 0x67, - 0xdf, 0x1c, 0x4e, 0x1f, 0xf5, 0x4d, 0x4d, 0xd8, 0x18, 0x4a, 0x5a, 0x2e, 0x24, 0xd1, 0xdd, 0x86, - 0xf5, 0x5e, 0x85, 0x4c, 0x95, 0x92, 0xc7, 0xc8, 0xce, 0x4d, 0x53, 0xcb, 0xc1, 0x7f, 0x5d, 0x64, - 0x7e, 0x3b, 0x9f, 0xe2, 0x1e, 0x45, 0xa0, 0xdd, 0x80, 0x69, 0x8c, 0x58, 0x80, 0x21, 0xb7, 0x3e, - 0x5b, 0x36, 0xec, 0xd3, 0xfb, 0x68, 0xc7, 0x7d, 0xdc, 0xe7, 0x55, 0xae, 0xac, 0x1e, 0x31, 0x98, - 0x8f, 0x2a, 0xcc, 0x55, 0x29, 0x79, 0xe2, 0x07, 0x64, 0x9b, 0xf9, 0x8d, 0x7f, 0xd0, 0xfb, 0x06, - 0x64, 0x44, 0x37, 0x34, 0x9f, 0xe6, 0x0b, 0xb4, 0x3c, 0xaa, 0xf9, 0xe1, 0x86, 0x84, 0x89, 0xca, - 0x54, 0xbc, 0x4d, 0x6e, 0x42, 0x1e, 0xe1, 0x65, 0x9e, 0x5b, 0x89, 0x19, 0xc9, 0xd1, 0x5a, 0x05, - 0xb8, 0x7c, 0xc2, 0xdd, 0x00, 0xfa, 0xa1, 0x02, 0x54, 0x29, 0x49, 0xf6, 0xe9, 0xbc, 0x4c, 0x2f, - 0xc2, 0x8c, 0xdc, 0x6f, 0x4c, 0x8c, 0x1f, 0x27, 0xb4, 0x3a, 0x4c, 0x7b, 0x2d, 0xec, 0x84, 0x4c, - 0x7a, 0x9f, 0x70, 0x79, 0xae, 0xc5, 0x76, 0xff, 0xea, 0x8a, 0x48, 0xe9, 0x11, 0x93, 0xc9, 0x81, - 0x76, 0x6c, 0x35, 0x99, 0x40, 0xf9, 0x57, 0x0a, 0xd2, 0x55, 0x4a, 0xb4, 0x2d, 0x98, 0x3d, 0xf1, - 0x54, 0x2c, 0x8d, 0x3a, 0x92, 0x53, 0x17, 0x48, 0x5f, 0x39, 0x53, 0xd9, 0xe0, 0x9e, 0xdd, 0x81, - 0x29, 0xbe, 0x5f, 0x0b, 0x63, 0x68, 0x31, 0xa8, 0x5f, 0x99, 0x00, 0x0e, 0x94, 0x9e, 0xc1, 0x85, - 0x3f, 0x36, 0x76, 0x1c, 0x69, 0xb8, 0x48, 0xbf, 0x7a, 0x86, 0xa2, 0xc1, 0x2f, 0x3c, 0x84, 0x4c, - 0xb2, 0x19, 0xc6, 0x18, 0x9e, 0xc4, 0xf5, 0xe5, 0xc9, 0x78, 0x22, 0x59, 0xa9, 0xec, 0x1d, 0x18, - 0xea, 0xfe, 0x81, 0xa1, 0x7e, 0x3b, 0x30, 0xd4, 0x37, 0x87, 0x86, 0xb2, 0x7f, 0x68, 0x28, 0x9f, - 0x0f, 0x0d, 0xe5, 0xe9, 0xe4, 0x23, 0xde, 0xe1, 0xff, 0x18, 0xfc, 0xa0, 0x6b, 0xd3, 0xfc, 0xa9, - 0xbe, 0xfe, 0x3b, 0x00, 0x00, 0xff, 0xff, 0xc9, 0x6e, 0x76, 0x95, 0x9d, 0x06, 0x00, 0x00, + // 653 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0x3f, 0x6f, 0xd3, 0x5e, + 0x14, 0xb5, 0x93, 0xfe, 0x9a, 0x5f, 0x6f, 0x50, 0x4b, 0xad, 0x08, 0x12, 0xb7, 0xb2, 0x23, 0xa3, + 0x56, 0x91, 0x50, 0x6d, 0x1a, 0x24, 0x86, 0x32, 0x91, 0xa2, 0x0a, 0x90, 0x22, 0xc0, 0x48, 0x20, + 0xb1, 0x14, 0x27, 0x71, 0x5d, 0x8b, 0xc4, 0xd7, 0xca, 0x7b, 0x89, 0x9a, 0x8d, 0x91, 0x09, 0x18, + 0x19, 0x3b, 0xb3, 0x21, 0xf1, 0x21, 0x0a, 0x53, 0x47, 0x06, 0x14, 0x50, 0xbb, 0x00, 0x62, 0xea, + 0x27, 0x40, 0x7e, 0x7f, 0xdc, 0xd2, 0xa6, 0x51, 0x91, 0xca, 0x94, 0xbc, 0x7b, 0xee, 0x39, 0xb9, + 0xe7, 0xbe, 0x7b, 0x5f, 0x60, 0xae, 0x89, 0xa4, 0x83, 0xc4, 0x09, 0xb0, 0xef, 0xf4, 0x97, 0x1b, + 0x3e, 0xf5, 0x96, 0x1d, 0xba, 0x65, 0xc7, 0x5d, 0xa4, 0xa8, 0x69, 0x1c, 0xb4, 0x03, 0xec, 0xdb, + 0x02, 0xd4, 0x0d, 0x41, 0x68, 0x78, 0xc4, 0x4f, 0x19, 0x4d, 0x0c, 0x23, 0xce, 0xd1, 0xe7, 0x47, + 0x08, 0x26, 0x7c, 0x8e, 0x96, 0x38, 0xba, 0xce, 0x4e, 0x8e, 0x90, 0xe7, 0x50, 0x21, 0xc0, 0x00, + 0x79, 0x3c, 0xf9, 0x26, 0x09, 0x01, 0x62, 0xd0, 0xf6, 0x1d, 0x76, 0x6a, 0xf4, 0x36, 0x1c, 0x2f, + 0x1a, 0x70, 0xc8, 0x7a, 0x9d, 0x81, 0xd9, 0x3a, 0x09, 0x1e, 0xf5, 0x1a, 0x9d, 0x90, 0x3e, 0xe8, + 0x62, 0x8c, 0xc4, 0x6b, 0x6b, 0x37, 0x21, 0xd7, 0xc4, 0x88, 0xfa, 0x11, 0x2d, 0xaa, 0x65, 0xb5, + 0x92, 0xaf, 0x16, 0x6c, 0x2e, 0x61, 0x4b, 0x09, 0xfb, 0x56, 0x34, 0xa8, 0xe5, 0x3f, 0x7d, 0x58, + 0xca, 0xad, 0xf2, 0x44, 0x57, 0x32, 0xb4, 0x57, 0x2a, 0xcc, 0x84, 0x51, 0x48, 0x43, 0xaf, 0xbd, + 0xde, 0xf2, 0x63, 0x24, 0x21, 0x2d, 0x66, 0xca, 0xd9, 0x4a, 0xbe, 0x5a, 0xb2, 0x45, 0xb1, 0x89, + 0x6f, 0xd9, 0x0c, 0x7b, 0x15, 0xc3, 0xa8, 0x76, 0x6f, 0x67, 0x68, 0x2a, 0x07, 0x43, 0xf3, 0xd2, + 0xc0, 0xeb, 0xb4, 0x57, 0xac, 0x63, 0x7c, 0xeb, 0xdd, 0x57, 0xb3, 0x12, 0x84, 0x74, 0xb3, 0xd7, + 0xb0, 0x9b, 0xd8, 0x11, 0x9e, 0xc5, 0xc7, 0x12, 0x69, 0x3d, 0x77, 0xe8, 0x20, 0xf6, 0x09, 0x93, + 0x22, 0xee, 0xb4, 0x60, 0xdf, 0xe6, 0x64, 0x4d, 0x87, 0xff, 0x63, 0xe6, 0xcc, 0xef, 0x16, 0xb3, + 0x65, 0xb5, 0x32, 0xe5, 0xa6, 0xe7, 0x95, 0x8b, 0x2f, 0xb7, 0x4d, 0xe5, 0xed, 0xb6, 0xa9, 0x7c, + 0xdf, 0x36, 0x95, 0x17, 0x5f, 0xca, 0x8a, 0xd5, 0x84, 0xd2, 0x89, 0x86, 0xb8, 0x3e, 0x89, 0x31, + 0x22, 0xbe, 0xb6, 0x06, 0xf9, 0x58, 0xc4, 0xd6, 0xc3, 0x16, 0x6b, 0xce, 0x44, 0x6d, 0xe1, 0xe7, + 0xd0, 0x3c, 0x1a, 0x3e, 0x18, 0x9a, 0x1a, 0xb7, 0x71, 0x24, 0x68, 0xb9, 0x20, 0x4f, 0x77, 0x5b, + 0xd6, 0x7b, 0x15, 0x72, 0x75, 0x12, 0x3c, 0x46, 0x7a, 0x6e, 0x9a, 0x5a, 0x01, 0xfe, 0xeb, 0x23, + 0xf5, 0xbb, 0xc5, 0x0c, 0xf3, 0xc8, 0x0f, 0xda, 0x0d, 0x98, 0xc4, 0x98, 0x86, 0x18, 0x31, 0xeb, + 0xd3, 0x55, 0xc3, 0x3e, 0x39, 0x8f, 0x76, 0x52, 0xc7, 0x7d, 0x96, 0xe5, 0x8a, 0xec, 0x11, 0x8d, + 0xf9, 0xa8, 0xc2, 0x8c, 0xa8, 0xf9, 0x89, 0x1f, 0x06, 0x9b, 0xd4, 0x6f, 0xfd, 0xe3, 0xda, 0xd7, + 0x20, 0xc7, 0xab, 0x21, 0xc5, 0x2c, 0x1b, 0xa0, 0xc5, 0x51, 0xc5, 0xcb, 0x62, 0x0e, 0x4d, 0xd4, + 0x26, 0x92, 0x69, 0x72, 0x25, 0x79, 0x84, 0x97, 0xd9, 0xd4, 0x8a, 0xbc, 0x5a, 0xab, 0x04, 0x97, + 0x8f, 0xb9, 0x4b, 0xa1, 0x1f, 0x2a, 0x40, 0x9d, 0x04, 0x72, 0x9e, 0xce, 0xcb, 0xf4, 0x3c, 0x4c, + 0x89, 0xf9, 0x46, 0x69, 0xfc, 0x30, 0xa0, 0x35, 0x61, 0xd2, 0xeb, 0x60, 0x2f, 0xa2, 0xc2, 0xfb, + 0x98, 0xe5, 0xb9, 0x96, 0xd8, 0xfd, 0xab, 0x15, 0x11, 0xd2, 0x23, 0x3a, 0x53, 0x00, 0xed, 0xd0, + 0xaa, 0xec, 0x40, 0xf5, 0x57, 0x06, 0xb2, 0x75, 0x12, 0x68, 0x1b, 0x30, 0x7d, 0xec, 0xa9, 0x58, + 0x18, 0x75, 0x25, 0x27, 0x16, 0x48, 0x5f, 0x3a, 0x53, 0x5a, 0xba, 0x67, 0x77, 0x60, 0x82, 0xed, + 0xc6, 0xdc, 0x29, 0xb4, 0x04, 0xd4, 0xaf, 0x8c, 0x01, 0x53, 0xa5, 0x67, 0x70, 0xe1, 0x8f, 0x89, + 0x1d, 0x47, 0x92, 0x49, 0xfa, 0xd5, 0x33, 0x24, 0xa5, 0xbf, 0xf0, 0x10, 0x72, 0x72, 0x32, 0x8c, + 0x53, 0x78, 0x02, 0xd7, 0x17, 0xc7, 0xe3, 0x52, 0xb2, 0x56, 0xdb, 0xd9, 0x33, 0xd4, 0xdd, 0x3d, + 0x43, 0xfd, 0xb6, 0x67, 0xa8, 0x6f, 0xf6, 0x0d, 0x65, 0x77, 0xdf, 0x50, 0x3e, 0xef, 0x1b, 0xca, + 0xd3, 0xf1, 0x57, 0xbc, 0xc5, 0xfe, 0x31, 0xd8, 0x45, 0x37, 0x26, 0xd9, 0x53, 0x7d, 0xfd, 0x77, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xbf, 0x6c, 0x75, 0x57, 0x9d, 0x06, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -420,7 +420,7 @@ type MsgClient interface { // Vote defines a method to add a vote on a specific proposal. Vote(ctx context.Context, in *MsgVote, opts ...grpc.CallOption) (*MsgVoteResponse, error) // WeightedVote defines a method to add a weighted vote on a specific proposal. - WeightedVote(ctx context.Context, in *MsgWeightedVote, opts ...grpc.CallOption) (*MsgWeightedVoteResponse, error) + VoteWeighted(ctx context.Context, in *MsgVoteWeighted, opts ...grpc.CallOption) (*MsgVoteWeightedResponse, error) // Deposit defines a method to add deposit on a specific proposal. Deposit(ctx context.Context, in *MsgDeposit, opts ...grpc.CallOption) (*MsgDepositResponse, error) } @@ -451,9 +451,9 @@ func (c *msgClient) Vote(ctx context.Context, in *MsgVote, opts ...grpc.CallOpti return out, nil } -func (c *msgClient) WeightedVote(ctx context.Context, in *MsgWeightedVote, opts ...grpc.CallOption) (*MsgWeightedVoteResponse, error) { - out := new(MsgWeightedVoteResponse) - err := c.cc.Invoke(ctx, "/cosmos.gov.v1beta1.Msg/WeightedVote", in, out, opts...) +func (c *msgClient) VoteWeighted(ctx context.Context, in *MsgVoteWeighted, opts ...grpc.CallOption) (*MsgVoteWeightedResponse, error) { + out := new(MsgVoteWeightedResponse) + err := c.cc.Invoke(ctx, "/cosmos.gov.v1beta1.Msg/VoteWeighted", in, out, opts...) if err != nil { return nil, err } @@ -476,7 +476,7 @@ type MsgServer interface { // Vote defines a method to add a vote on a specific proposal. Vote(context.Context, *MsgVote) (*MsgVoteResponse, error) // WeightedVote defines a method to add a weighted vote on a specific proposal. - WeightedVote(context.Context, *MsgWeightedVote) (*MsgWeightedVoteResponse, error) + VoteWeighted(context.Context, *MsgVoteWeighted) (*MsgVoteWeightedResponse, error) // Deposit defines a method to add deposit on a specific proposal. Deposit(context.Context, *MsgDeposit) (*MsgDepositResponse, error) } @@ -491,8 +491,8 @@ func (*UnimplementedMsgServer) SubmitProposal(ctx context.Context, req *MsgSubmi func (*UnimplementedMsgServer) Vote(ctx context.Context, req *MsgVote) (*MsgVoteResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Vote not implemented") } -func (*UnimplementedMsgServer) WeightedVote(ctx context.Context, req *MsgWeightedVote) (*MsgWeightedVoteResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method WeightedVote not implemented") +func (*UnimplementedMsgServer) VoteWeighted(ctx context.Context, req *MsgVoteWeighted) (*MsgVoteWeightedResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VoteWeighted not implemented") } func (*UnimplementedMsgServer) Deposit(ctx context.Context, req *MsgDeposit) (*MsgDepositResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Deposit not implemented") @@ -538,20 +538,20 @@ func _Msg_Vote_Handler(srv interface{}, ctx context.Context, dec func(interface{ return interceptor(ctx, in, info, handler) } -func _Msg_WeightedVote_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgWeightedVote) +func _Msg_VoteWeighted_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgVoteWeighted) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(MsgServer).WeightedVote(ctx, in) + return srv.(MsgServer).VoteWeighted(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/cosmos.gov.v1beta1.Msg/WeightedVote", + FullMethod: "/cosmos.gov.v1beta1.Msg/VoteWeighted", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).WeightedVote(ctx, req.(*MsgWeightedVote)) + return srv.(MsgServer).VoteWeighted(ctx, req.(*MsgVoteWeighted)) } return interceptor(ctx, in, info, handler) } @@ -587,8 +587,8 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ Handler: _Msg_Vote_Handler, }, { - MethodName: "WeightedVote", - Handler: _Msg_WeightedVote_Handler, + MethodName: "VoteWeighted", + Handler: _Msg_VoteWeighted_Handler, }, { MethodName: "Deposit", @@ -723,7 +723,7 @@ func (m *MsgVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *MsgWeightedVote) Marshal() (dAtA []byte, err error) { +func (m *MsgVoteWeighted) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -733,12 +733,12 @@ func (m *MsgWeightedVote) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *MsgWeightedVote) MarshalTo(dAtA []byte) (int, error) { +func (m *MsgVoteWeighted) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *MsgWeightedVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *MsgVoteWeighted) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -795,7 +795,7 @@ func (m *MsgVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *MsgWeightedVoteResponse) Marshal() (dAtA []byte, err error) { +func (m *MsgVoteWeightedResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -805,12 +805,12 @@ func (m *MsgWeightedVoteResponse) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *MsgWeightedVoteResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *MsgVoteWeightedResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *MsgWeightedVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *MsgVoteWeightedResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -955,7 +955,7 @@ func (m *MsgVote) Size() (n int) { return n } -func (m *MsgWeightedVote) Size() (n int) { +func (m *MsgVoteWeighted) Size() (n int) { if m == nil { return 0 } @@ -986,7 +986,7 @@ func (m *MsgVoteResponse) Size() (n int) { return n } -func (m *MsgWeightedVoteResponse) Size() (n int) { +func (m *MsgVoteWeightedResponse) Size() (n int) { if m == nil { return 0 } @@ -1373,7 +1373,7 @@ func (m *MsgVote) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgWeightedVote) Unmarshal(dAtA []byte) error { +func (m *MsgVoteWeighted) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1396,10 +1396,10 @@ func (m *MsgWeightedVote) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgWeightedVote: wiretype end group for non-group") + return fmt.Errorf("proto: MsgVoteWeighted: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgWeightedVote: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgVoteWeighted: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -1558,7 +1558,7 @@ func (m *MsgVoteResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgWeightedVoteResponse) Unmarshal(dAtA []byte) error { +func (m *MsgVoteWeightedResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1581,10 +1581,10 @@ func (m *MsgWeightedVoteResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgWeightedVoteResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgVoteWeightedResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgWeightedVoteResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgVoteWeightedResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: From c95de9c4177442dee4c69d96917efc955b5d19d9 Mon Sep 17 00:00:00 2001 From: MD Aleem <72057206+aleem1314@users.noreply.github.com> Date: Mon, 25 Jan 2021 22:11:30 +0530 Subject: [PATCH 076/152] implement x/authz module (#7629) * WIP: Msg authorization module added * fixing errors * fixed errors * fixed module.go * Add msg_tests * fixes compile issues * fix test * fix test * Add msg types tests * Fix Getmsgs * fixed codec issue * Fix syntax issues * Fix keeper * fixed proto issues * Fix keeper tests * fixed router in keeper * Fix query proto * Fix cli txs * Add grpc query client implementation * Add grpc-keeper test * Add grpc query tests Add revoke and exec authorization cli commands * Fix linting issues * Fix cli query * fix lint errors * Add Genesis state * Fix query authorization * Review changes * Fix grant authorization handler * Add cli tests * Add cli tests * Fix genesis test * Fix issues * update module to use proto msg services * Add simultion tests * Fix lint * fix lint * WIP simulations * WIP simulations * add msg tests * Fix simulation * Fix errors * fix genesis import export * fix sim tests * fix sim * fix test * Register RegisterMsgServer * WIP * WIP * Update keeper test * change msg_authorization module name to authz * changed type conversion for serviceMsg * serviceMsg change to any * Fix issues * fix msg tests * fix errors * proto format * remove LegacyQuerierHandler * Use MsgServiceRouter * fix keeper-test * fix query authorizations * fix NewCmdSendAs * fix simtests * fix error * fix lint * fix lint * add tests for generic authorization * fix imports * format * Update error message * remove println * add query all grants * Add pagination for queries * format * fix lint * review changes * fix grpc tests * add pagination to cli query * review changes * replace panic with error * lint * fix errors * fix tests * remove gogoproto extensions * update function doc * review changes * fix errors * fix query flags * fix grpc query test * init service-msg * remove unsed field * add proto-codec for simulations * fix codec issue * update authz simulations * change msgauth to authz * add check for invalid msg-type * change expiration flag to Unix * doc * update module.go * fix sims * fix grant-authorization sims * fix error * fix error * add build flag * fix codec issue * rename * review changes * format * review changes * go.mod * refactor * proto-gen * Update x/authz/keeper/grpc_query_test.go Co-authored-by: Amaury * Update x/authz/keeper/grpc_query_test.go Co-authored-by: Amaury * Update x/authz/keeper/grpc_query_test.go Co-authored-by: Amaury * Fix review comments * fix protogen * Follow Msg...Request style for msg requests * update comment * Fix error codes * fix review comment * improve msg validations * Handle error in casting msgs * rename actor => grantStoreKey * add godoc * add godoc * Fix simulations * Fix cli, cli_tests * Fix simulations * rename to GetOrRevokeAuthorization * Move events to keeper * Fix fmt * Update x/authz/client/cli/tx.go Co-authored-by: Amaury * rename actor * fix lint Co-authored-by: atheesh Co-authored-by: atheeshp <59333759+atheeshp@users.noreply.github.com> Co-authored-by: Amaury Martiny Co-authored-by: MD Aleem <72057206+aleem1413@users.noreply.github.com> Co-authored-by: Anil Kumar Kammari --- docs/core/proto-docs.md | 977 ++++++++----- proto/cosmos/authz/v1beta1/authz.proto | 37 + proto/cosmos/authz/v1beta1/genesis.proto | 24 + proto/cosmos/authz/v1beta1/query.proto | 54 + proto/cosmos/authz/v1beta1/tx.proto | 62 + simapp/app.go | 14 +- simapp/sim_test.go | 2 + types/errors/errors.go | 3 + types/msgservice/service_msg_client.go | 50 + types/simulation/types.go | 13 +- x/authz/client/cli/cli_test.go | 727 ++++++++++ x/authz/client/cli/query.go | 138 ++ x/authz/client/cli/tx.go | 222 +++ x/authz/client/rest/grpc_query_test.go | 235 ++++ x/authz/client/testutil/test_helpers.go | 34 + x/authz/exported/keeper.go | 26 + x/authz/genesis.go | 47 + x/authz/genesis_test.go | 59 + x/authz/keeper/grpc_query.go | 120 ++ x/authz/keeper/grpc_query_test.go | 157 +++ x/authz/keeper/keeper.go | 210 +++ x/authz/keeper/keeper_test.go | 218 +++ x/authz/keeper/msg_server.go | 75 + x/authz/module.go | 194 +++ x/authz/simulation/decoder.go | 26 + x/authz/simulation/decoder_test.go | 50 + x/authz/simulation/genesis.go | 38 + x/authz/simulation/genesis_test.go | 40 + x/authz/simulation/operations.go | 291 ++++ x/authz/simulation/operations_test.go | 197 +++ x/authz/types/authorizations.go | 63 + x/authz/types/authz.pb.go | 759 ++++++++++ x/authz/types/codec.go | 25 + x/authz/types/errors.go | 10 + x/authz/types/events.go | 14 + x/authz/types/expected_keepers.go | 16 + x/authz/types/generic_authorization.go | 28 + x/authz/types/genesis.go | 41 + x/authz/types/genesis.pb.go | 680 +++++++++ x/authz/types/keys.go | 41 + x/authz/types/keys_test.go | 20 + x/authz/types/msgs.go | 215 +++ x/authz/types/msgs_test.go | 103 ++ x/authz/types/query.pb.go | 1278 +++++++++++++++++ x/authz/types/query.pb.gw.go | 362 +++++ x/authz/types/send_authorization.go | 45 + x/authz/types/tx.pb.go | 1609 ++++++++++++++++++++++ x/bank/client/testutil/cli_helpers.go | 39 +- x/bank/simulation/operations.go | 4 +- x/distribution/simulation/operations.go | 8 +- x/gov/simulation/operations.go | 6 +- x/slashing/simulation/operations.go | 10 +- x/staking/simulation/operations.go | 10 +- x/staking/types/tx.pb.go | 9 +- 54 files changed, 9360 insertions(+), 375 deletions(-) create mode 100644 proto/cosmos/authz/v1beta1/authz.proto create mode 100644 proto/cosmos/authz/v1beta1/genesis.proto create mode 100644 proto/cosmos/authz/v1beta1/query.proto create mode 100644 proto/cosmos/authz/v1beta1/tx.proto create mode 100644 types/msgservice/service_msg_client.go create mode 100644 x/authz/client/cli/cli_test.go create mode 100644 x/authz/client/cli/query.go create mode 100644 x/authz/client/cli/tx.go create mode 100644 x/authz/client/rest/grpc_query_test.go create mode 100644 x/authz/client/testutil/test_helpers.go create mode 100644 x/authz/exported/keeper.go create mode 100644 x/authz/genesis.go create mode 100644 x/authz/genesis_test.go create mode 100644 x/authz/keeper/grpc_query.go create mode 100644 x/authz/keeper/grpc_query_test.go create mode 100644 x/authz/keeper/keeper.go create mode 100644 x/authz/keeper/keeper_test.go create mode 100644 x/authz/keeper/msg_server.go create mode 100644 x/authz/module.go create mode 100644 x/authz/simulation/decoder.go create mode 100644 x/authz/simulation/decoder_test.go create mode 100644 x/authz/simulation/genesis.go create mode 100644 x/authz/simulation/genesis_test.go create mode 100644 x/authz/simulation/operations.go create mode 100644 x/authz/simulation/operations_test.go create mode 100644 x/authz/types/authorizations.go create mode 100644 x/authz/types/authz.pb.go create mode 100644 x/authz/types/codec.go create mode 100644 x/authz/types/errors.go create mode 100644 x/authz/types/events.go create mode 100644 x/authz/types/expected_keepers.go create mode 100644 x/authz/types/generic_authorization.go create mode 100644 x/authz/types/genesis.go create mode 100644 x/authz/types/genesis.pb.go create mode 100644 x/authz/types/keys.go create mode 100644 x/authz/types/keys_test.go create mode 100644 x/authz/types/msgs.go create mode 100644 x/authz/types/msgs_test.go create mode 100644 x/authz/types/query.pb.go create mode 100644 x/authz/types/query.pb.gw.go create mode 100644 x/authz/types/send_authorization.go create mode 100644 x/authz/types/tx.pb.go diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index d49cf8634bce..ec30ba730ba1 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -26,6 +26,49 @@ - [DecProto](#cosmos.base.v1beta1.DecProto) - [IntProto](#cosmos.base.v1beta1.IntProto) +- [cosmos/authz/v1beta1/authz.proto](#cosmos/authz/v1beta1/authz.proto) + - [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) + - [GenericAuthorization](#cosmos.authz.v1beta1.GenericAuthorization) + - [SendAuthorization](#cosmos.authz.v1beta1.SendAuthorization) + +- [cosmos/base/abci/v1beta1/abci.proto](#cosmos/base/abci/v1beta1/abci.proto) + - [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) + - [Attribute](#cosmos.base.abci.v1beta1.Attribute) + - [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) + - [MsgData](#cosmos.base.abci.v1beta1.MsgData) + - [Result](#cosmos.base.abci.v1beta1.Result) + - [SearchTxsResult](#cosmos.base.abci.v1beta1.SearchTxsResult) + - [SimulationResponse](#cosmos.base.abci.v1beta1.SimulationResponse) + - [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) + - [TxMsgData](#cosmos.base.abci.v1beta1.TxMsgData) + - [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) + +- [cosmos/authz/v1beta1/tx.proto](#cosmos/authz/v1beta1/tx.proto) + - [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) + - [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) + - [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) + - [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) + - [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) + - [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) + + - [Msg](#cosmos.authz.v1beta1.Msg) + +- [cosmos/authz/v1beta1/genesis.proto](#cosmos/authz/v1beta1/genesis.proto) + - [GenesisState](#cosmos.authz.v1beta1.GenesisState) + - [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) + +- [cosmos/base/query/v1beta1/pagination.proto](#cosmos/base/query/v1beta1/pagination.proto) + - [PageRequest](#cosmos.base.query.v1beta1.PageRequest) + - [PageResponse](#cosmos.base.query.v1beta1.PageResponse) + +- [cosmos/authz/v1beta1/query.proto](#cosmos/authz/v1beta1/query.proto) + - [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) + - [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) + - [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) + - [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) + + - [Query](#cosmos.authz.v1beta1.Query) + - [cosmos/bank/v1beta1/bank.proto](#cosmos/bank/v1beta1/bank.proto) - [DenomUnit](#cosmos.bank.v1beta1.DenomUnit) - [Input](#cosmos.bank.v1beta1.Input) @@ -39,10 +82,6 @@ - [Balance](#cosmos.bank.v1beta1.Balance) - [GenesisState](#cosmos.bank.v1beta1.GenesisState) -- [cosmos/base/query/v1beta1/pagination.proto](#cosmos/base/query/v1beta1/pagination.proto) - - [PageRequest](#cosmos.base.query.v1beta1.PageRequest) - - [PageResponse](#cosmos.base.query.v1beta1.PageResponse) - - [cosmos/bank/v1beta1/query.proto](#cosmos/bank/v1beta1/query.proto) - [QueryAllBalancesRequest](#cosmos.bank.v1beta1.QueryAllBalancesRequest) - [QueryAllBalancesResponse](#cosmos.bank.v1beta1.QueryAllBalancesResponse) @@ -69,18 +108,6 @@ - [Msg](#cosmos.bank.v1beta1.Msg) -- [cosmos/base/abci/v1beta1/abci.proto](#cosmos/base/abci/v1beta1/abci.proto) - - [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) - - [Attribute](#cosmos.base.abci.v1beta1.Attribute) - - [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) - - [MsgData](#cosmos.base.abci.v1beta1.MsgData) - - [Result](#cosmos.base.abci.v1beta1.Result) - - [SearchTxsResult](#cosmos.base.abci.v1beta1.SearchTxsResult) - - [SimulationResponse](#cosmos.base.abci.v1beta1.SimulationResponse) - - [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) - - [TxMsgData](#cosmos.base.abci.v1beta1.TxMsgData) - - [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) - - [cosmos/base/kv/v1beta1/kv.proto](#cosmos/base/kv/v1beta1/kv.proto) - [Pair](#cosmos.base.kv.v1beta1.Pair) - [Pairs](#cosmos.base.kv.v1beta1.Pairs) @@ -960,238 +987,253 @@ IntProto defines a Protobuf wrapper around an Int object. - +

      Top

      -## cosmos/bank/v1beta1/bank.proto +## cosmos/authz/v1beta1/authz.proto - + -### DenomUnit -DenomUnit represents a struct that describes a given -denomination unit of the basic token. +### AuthorizationGrant +AuthorizationGrant gives permissions to execute +the provide method with expiration time. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | denom represents the string name of the given denom unit (e.g uatom). | -| `exponent` | [uint32](#uint32) | | exponent represents power of 10 exponent that one must raise the base_denom to in order to equal the given DenomUnit's denom 1 denom = 1^exponent base_denom (e.g. with a base_denom of uatom, one can create a DenomUnit of 'atom' with exponent = 6, thus: 1 atom = 10^6 uatom). | -| `aliases` | [string](#string) | repeated | aliases is a list of string aliases for the given denom | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - + -### Input -Input models transaction input. +### GenericAuthorization +GenericAuthorization gives the grantee unrestricted permissions to execute +the provided method on behalf of the granter's account. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `method_name` | [string](#string) | | method name to grant unrestricted permissions to execute Note: MethodName() is already a method on `GenericAuthorization` type, we need some custom naming here so using `MessageName` | - + -### Metadata -Metadata represents a struct that describes -a basic token. +### SendAuthorization +SendAuthorization allows the grantee to spend up to spend_limit coins from +the granter's account. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `description` | [string](#string) | | | -| `denom_units` | [DenomUnit](#cosmos.bank.v1beta1.DenomUnit) | repeated | denom_units represents the list of DenomUnit's for a given coin | -| `base` | [string](#string) | | base represents the base denom (should be the DenomUnit with exponent = 0). | -| `display` | [string](#string) | | display indicates the suggested denom that should be displayed in clients. | +| `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | + - + -### Output -Output models transaction outputs. + + + + + + + +

      Top

      + +## cosmos/base/abci/v1beta1/abci.proto + + + + + +### ABCIMessageLog +ABCIMessageLog defines a structure containing an indexed tx ABCI message log. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `msg_index` | [uint32](#uint32) | | | +| `log` | [string](#string) | | | +| `events` | [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) | repeated | Events contains a slice of Event objects that were emitted during some execution. | - + -### Params -Params defines the parameters for the bank module. +### Attribute +Attribute defines an attribute wrapper where the key and value are +strings instead of raw bytes. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `send_enabled` | [SendEnabled](#cosmos.bank.v1beta1.SendEnabled) | repeated | | -| `default_send_enabled` | [bool](#bool) | | | +| `key` | [string](#string) | | | +| `value` | [string](#string) | | | - + -### SendEnabled -SendEnabled maps coin denom to a send_enabled status (whether a denom is -sendable). +### GasInfo +GasInfo defines tx execution gas context. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | | -| `enabled` | [bool](#bool) | | | +| `gas_wanted` | [uint64](#uint64) | | GasWanted is the maximum units of work we allow this tx to perform. | +| `gas_used` | [uint64](#uint64) | | GasUsed is the amount of gas actually consumed. | - + -### Supply -Supply represents a struct that passively keeps track of the total supply -amounts in the network. +### MsgData +MsgData defines the data returned in a Result object during message +execution. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `total` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `msg_type` | [string](#string) | | | +| `data` | [bytes](#bytes) | | | - - + - +### Result +Result is the union of ResponseFormat and ResponseCheckTx. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `data` | [bytes](#bytes) | | Data is any data returned from message or handler execution. It MUST be length prefixed in order to separate data from multiple message executions. | +| `log` | [string](#string) | | Log contains the log information from message or handler execution. | +| `events` | [tendermint.abci.Event](#tendermint.abci.Event) | repeated | Events contains a slice of Event objects that were emitted during message or handler execution. | - -

      Top

      -## cosmos/bank/v1beta1/genesis.proto - + -### Balance -Balance defines an account address and balance pair used in the bank module's -genesis state. +### SearchTxsResult +SearchTxsResult defines a structure for querying txs pageable | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the address of the balance holder. | -| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | coins defines the different coins this balance holds. | +| `total_count` | [uint64](#uint64) | | Count of all txs | +| `count` | [uint64](#uint64) | | Count of txs in current page | +| `page_number` | [uint64](#uint64) | | Index of current page, start from 1 | +| `page_total` | [uint64](#uint64) | | Count of total pages | +| `limit` | [uint64](#uint64) | | Max count txs per page | +| `txs` | [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | List of txs in current page | - + -### GenesisState -GenesisState defines the bank module's genesis state. +### SimulationResponse +SimulationResponse defines the response generated when a transaction is +successfully simulated. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.bank.v1beta1.Params) | | params defines all the paramaters of the module. | -| `balances` | [Balance](#cosmos.bank.v1beta1.Balance) | repeated | balances is an array containing the balances of all the accounts. | -| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply represents the total supply. | -| `denom_metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | denom_metadata defines the metadata of the differents coins. | - +| `gas_info` | [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | | +| `result` | [Result](#cosmos.base.abci.v1beta1.Result) | | | - - - + - +### StringEvent +StringEvent defines en Event object wrapper where all the attributes +contain key/value pairs that are strings instead of raw bytes. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `type` | [string](#string) | | | +| `attributes` | [Attribute](#cosmos.base.abci.v1beta1.Attribute) | repeated | | - -

      Top

      -## cosmos/base/query/v1beta1/pagination.proto - -### PageRequest -PageRequest is to be embedded in gRPC request messages for efficient -pagination. Ex: + - message SomeRequest { - Foo some_parameter = 1; - PageRequest pagination = 2; - } +### TxMsgData +TxMsgData defines a list of MsgData. A transaction will have a MsgData object +for each message. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | key is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be set. | -| `offset` | [uint64](#uint64) | | offset is a numeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be set. | -| `limit` | [uint64](#uint64) | | limit is the total number of results to be returned in the result page. If left empty it will default to a value to be set by each app. | -| `count_total` | [bool](#bool) | | count_total is set to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. count_total is only respected when offset is used. It is ignored when key is set. | - +| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | | - -### PageResponse -PageResponse is to be embedded in gRPC response messages where the -corresponding request message has used PageRequest. + - message SomeResponse { - repeated Bar results = 1; - PageResponse page = 2; - } +### TxResponse +TxResponse defines a structure containing relevant tx data and metadata. The +tags are stringified and the log is JSON decoded. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `next_key` | [bytes](#bytes) | | next_key is the key to be passed to PageRequest.key to query the next page most efficiently | -| `total` | [uint64](#uint64) | | total is total number of results available if PageRequest.count_total was set, its value is undefined otherwise | +| `height` | [int64](#int64) | | The block height | +| `txhash` | [string](#string) | | The transaction hash. | +| `codespace` | [string](#string) | | Namespace for the Code | +| `code` | [uint32](#uint32) | | Response code. | +| `data` | [string](#string) | | Result bytes, if any. | +| `raw_log` | [string](#string) | | The output of the application's logger (raw string). May be non-deterministic. | +| `logs` | [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) | repeated | The output of the application's logger (typed). May be non-deterministic. | +| `info` | [string](#string) | | Additional information. May be non-deterministic. | +| `gas_wanted` | [int64](#int64) | | Amount of gas requested for transaction. | +| `gas_used` | [int64](#int64) | | Amount of gas consumed by transaction. | +| `tx` | [google.protobuf.Any](#google.protobuf.Any) | | The request transaction bytes. | +| `timestamp` | [string](#string) | | Time of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time. | @@ -1207,216 +1249,220 @@ corresponding request message has used PageRequest. - +

      Top

      -## cosmos/bank/v1beta1/query.proto +## cosmos/authz/v1beta1/tx.proto - + -### QueryAllBalancesRequest -QueryBalanceRequest is the request type for the Query/AllBalances RPC method. +### MsgExecAuthorizedRequest +MsgExecAuthorizedRequest attempts to execute the provided messages using +authorizations granted to the grantee. Each message should have only +one signer corresponding to the granter of the authorization. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the address to query balances for. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +| `grantee` | [string](#string) | | | +| `msgs` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | - + -### QueryAllBalancesResponse -QueryAllBalancesResponse is the response type for the Query/AllBalances RPC -method. +### MsgExecAuthorizedResponse +MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse response type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `balances` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | balances is the balances of all the coins. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | | - + -### QueryBalanceRequest -QueryBalanceRequest is the request type for the Query/Balance RPC method. +### MsgGrantAuthorizationRequest +MsgGrantAuthorizationRequest grants the provided authorization to the grantee on the granter's +account with the provided expiration time. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the address to query balances for. | -| `denom` | [string](#string) | | denom is the coin denom to query balances for. | - +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - - -### QueryBalanceResponse -QueryBalanceResponse is the response type for the Query/Balance RPC method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | balance is the balance of the coin. | +### MsgGrantAuthorizationResponse +MsgGrantAuthorizationResponse defines the Msg/MsgGrantAuthorization response type. - + -### QueryDenomMetadataRequest -QueryDenomMetadataRequest is the request type for the Query/DenomMetadata RPC method. +### MsgRevokeAuthorizationRequest +MsgRevokeAuthorizationRequest revokes any authorization with the provided sdk.Msg type on the +granter's account with that has been granted to the grantee. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | denom is the coin denom to query the metadata for. | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `method_name` | [string](#string) | | | - - -### QueryDenomMetadataResponse -QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC -method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | | metadata describes and provides all the client information for the requested token. | - + +### MsgRevokeAuthorizationResponse +MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse response type. - - -### QueryDenomsMetadataRequest -QueryDenomsMetadataRequest is the request type for the Query/DenomsMetadata RPC method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + + + +### Msg +Msg defines the authz Msg service. +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `GrantAuthorization` | [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) | [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) | GrantAuthorization grants the provided authorization to the grantee on the granter's account with the provided expiration time. | | +| `ExecAuthorized` | [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) | [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) | ExecAuthorized attempts to execute the provided messages using authorizations granted to the grantee. Each message should have only one signer corresponding to the granter of the authorization. | | +| `RevokeAuthorization` | [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) | [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) | RevokeAuthorization revokes any authorization corresponding to the provided method name on the granter's account that has been granted to the grantee. | | - + -### QueryDenomsMetadataResponse -QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata RPC -method. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `metadatas` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | metadata provides the client information for all the registered tokens. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | + +

      Top

      +## cosmos/authz/v1beta1/genesis.proto + +### GenesisState +GenesisState defines the authz module's genesis state. - -### QueryParamsRequest -QueryParamsRequest defines the request type for querying x/bank parameters. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `authorization` | [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) | repeated | | - + -### QueryParamsResponse -QueryParamsResponse defines the response type for querying x/bank parameters. +### GrantAuthorization +GrantAuthorization defines the GenesisState/GrantAuthorization type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.bank.v1beta1.Params) | | | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | + - + -### QuerySupplyOfRequest -QuerySupplyOfRequest is the request type for the Query/SupplyOf RPC method. + + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | denom is the coin denom to query balances for. | + +

      Top

      +## cosmos/base/query/v1beta1/pagination.proto + - +### PageRequest +PageRequest is to be embedded in gRPC request messages for efficient +pagination. Ex: -### QuerySupplyOfResponse -QuerySupplyOfResponse is the response type for the Query/SupplyOf RPC method. + message SomeRequest { + Foo some_parameter = 1; + PageRequest pagination = 2; + } | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | amount is the supply of the coin. | - - - - - - - +| `key` | [bytes](#bytes) | | key is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be set. | +| `offset` | [uint64](#uint64) | | offset is a numeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be set. | +| `limit` | [uint64](#uint64) | | limit is the total number of results to be returned in the result page. If left empty it will default to a value to be set by each app. | +| `count_total` | [bool](#bool) | | count_total is set to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. count_total is only respected when offset is used. It is ignored when key is set. | -### QueryTotalSupplyRequest -QueryTotalSupplyRequest is the request type for the Query/TotalSupply RPC -method. + - +### PageResponse +PageResponse is to be embedded in gRPC response messages where the +corresponding request message has used PageRequest. -### QueryTotalSupplyResponse -QueryTotalSupplyResponse is the response type for the Query/TotalSupply RPC -method + message SomeResponse { + repeated Bar results = 1; + PageResponse page = 2; + } | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply is the supply of the coins | +| `next_key` | [bytes](#bytes) | | next_key is the key to be passed to PageRequest.key to query the next page most efficiently | +| `total` | [uint64](#uint64) | | total is total number of results available if PageRequest.count_total was set, its value is undefined otherwise | @@ -1428,80 +1474,76 @@ method - - - -### Query -Query defines the gRPC querier service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Balance` | [QueryBalanceRequest](#cosmos.bank.v1beta1.QueryBalanceRequest) | [QueryBalanceResponse](#cosmos.bank.v1beta1.QueryBalanceResponse) | Balance queries the balance of a single coin for a single account. | GET|/cosmos/bank/v1beta1/balances/{address}/{denom}| -| `AllBalances` | [QueryAllBalancesRequest](#cosmos.bank.v1beta1.QueryAllBalancesRequest) | [QueryAllBalancesResponse](#cosmos.bank.v1beta1.QueryAllBalancesResponse) | AllBalances queries the balance of all coins for a single account. | GET|/cosmos/bank/v1beta1/balances/{address}| -| `TotalSupply` | [QueryTotalSupplyRequest](#cosmos.bank.v1beta1.QueryTotalSupplyRequest) | [QueryTotalSupplyResponse](#cosmos.bank.v1beta1.QueryTotalSupplyResponse) | TotalSupply queries the total supply of all coins. | GET|/cosmos/bank/v1beta1/supply| -| `SupplyOf` | [QuerySupplyOfRequest](#cosmos.bank.v1beta1.QuerySupplyOfRequest) | [QuerySupplyOfResponse](#cosmos.bank.v1beta1.QuerySupplyOfResponse) | SupplyOf queries the supply of a single coin. | GET|/cosmos/bank/v1beta1/supply/{denom}| -| `Params` | [QueryParamsRequest](#cosmos.bank.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.bank.v1beta1.QueryParamsResponse) | Params queries the parameters of x/bank module. | GET|/cosmos/bank/v1beta1/params| -| `DenomMetadata` | [QueryDenomMetadataRequest](#cosmos.bank.v1beta1.QueryDenomMetadataRequest) | [QueryDenomMetadataResponse](#cosmos.bank.v1beta1.QueryDenomMetadataResponse) | DenomsMetadata queries the client metadata of a given coin denomination. | GET|/cosmos/bank/v1beta1/denoms_metadata/{denom}| -| `DenomsMetadata` | [QueryDenomsMetadataRequest](#cosmos.bank.v1beta1.QueryDenomsMetadataRequest) | [QueryDenomsMetadataResponse](#cosmos.bank.v1beta1.QueryDenomsMetadataResponse) | DenomsMetadata queries the client metadata for all registered coin denominations. | GET|/cosmos/bank/v1beta1/denoms_metadata| - - +

      Top

      -## cosmos/bank/v1beta1/tx.proto +## cosmos/authz/v1beta1/query.proto - + -### MsgMultiSend -MsgMultiSend represents an arbitrary multi-in, multi-out send message. +### QueryAuthorizationRequest +QueryAuthorizationRequest is the request type for the Query/Authorization RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `inputs` | [Input](#cosmos.bank.v1beta1.Input) | repeated | | -| `outputs` | [Output](#cosmos.bank.v1beta1.Output) | repeated | | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `method_name` | [string](#string) | | | - + -### MsgMultiSendResponse -MsgMultiSendResponse defines the Msg/MultiSend response type. +### QueryAuthorizationResponse +QueryAuthorizationResponse is the response type for the Query/Authorization RPC method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `authorization` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | | authorization is a authorization granted for grantee by granter. | + - -### MsgSend -MsgSend represents a message to send coins from one account to another. + + +### QueryAuthorizationsRequest +QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `from_address` | [string](#string) | | | -| `to_address` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - + -### MsgSendResponse -MsgSendResponse defines the Msg/Send response type. +### QueryAuthorizationsResponse +QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `authorizations` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | repeated | authorizations is a list of grants granted for grantee by granter. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | @@ -1514,202 +1556,190 @@ MsgSendResponse defines the Msg/Send response type. - + -### Msg -Msg defines the bank Msg service. +### Query +Query defines the gRPC querier service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Send` | [MsgSend](#cosmos.bank.v1beta1.MsgSend) | [MsgSendResponse](#cosmos.bank.v1beta1.MsgSendResponse) | Send defines a method for sending coins from one account to another account. | | -| `MultiSend` | [MsgMultiSend](#cosmos.bank.v1beta1.MsgMultiSend) | [MsgMultiSendResponse](#cosmos.bank.v1beta1.MsgMultiSendResponse) | MultiSend defines a method for sending coins from some accounts to other accounts. | | +| `Authorization` | [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) | [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) | Returns any `Authorization` (or `nil`), with the expiration time, granted to the grantee by the granter for the provided msg type. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grant| +| `Authorizations` | [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) | [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) | Returns list of `Authorization`, granted to the grantee by the granter. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grants| - +

      Top

      -## cosmos/base/abci/v1beta1/abci.proto +## cosmos/bank/v1beta1/bank.proto - + -### ABCIMessageLog -ABCIMessageLog defines a structure containing an indexed tx ABCI message log. +### DenomUnit +DenomUnit represents a struct that describes a given +denomination unit of the basic token. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `msg_index` | [uint32](#uint32) | | | -| `log` | [string](#string) | | | -| `events` | [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) | repeated | Events contains a slice of Event objects that were emitted during some execution. | +| `denom` | [string](#string) | | denom represents the string name of the given denom unit (e.g uatom). | +| `exponent` | [uint32](#uint32) | | exponent represents power of 10 exponent that one must raise the base_denom to in order to equal the given DenomUnit's denom 1 denom = 1^exponent base_denom (e.g. with a base_denom of uatom, one can create a DenomUnit of 'atom' with exponent = 6, thus: 1 atom = 10^6 uatom). | +| `aliases` | [string](#string) | repeated | aliases is a list of string aliases for the given denom | - + -### Attribute -Attribute defines an attribute wrapper where the key and value are -strings instead of raw bytes. +### Input +Input models transaction input. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [string](#string) | | | -| `value` | [string](#string) | | | +| `address` | [string](#string) | | | +| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - + -### GasInfo -GasInfo defines tx execution gas context. +### Metadata +Metadata represents a struct that describes +a basic token. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `gas_wanted` | [uint64](#uint64) | | GasWanted is the maximum units of work we allow this tx to perform. | -| `gas_used` | [uint64](#uint64) | | GasUsed is the amount of gas actually consumed. | +| `description` | [string](#string) | | | +| `denom_units` | [DenomUnit](#cosmos.bank.v1beta1.DenomUnit) | repeated | denom_units represents the list of DenomUnit's for a given coin | +| `base` | [string](#string) | | base represents the base denom (should be the DenomUnit with exponent = 0). | +| `display` | [string](#string) | | display indicates the suggested denom that should be displayed in clients. | - + -### MsgData -MsgData defines the data returned in a Result object during message -execution. +### Output +Output models transaction outputs. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `msg_type` | [string](#string) | | | -| `data` | [bytes](#bytes) | | | +| `address` | [string](#string) | | | +| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - + -### Result -Result is the union of ResponseFormat and ResponseCheckTx. +### Params +Params defines the parameters for the bank module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `data` | [bytes](#bytes) | | Data is any data returned from message or handler execution. It MUST be length prefixed in order to separate data from multiple message executions. | -| `log` | [string](#string) | | Log contains the log information from message or handler execution. | -| `events` | [tendermint.abci.Event](#tendermint.abci.Event) | repeated | Events contains a slice of Event objects that were emitted during message or handler execution. | +| `send_enabled` | [SendEnabled](#cosmos.bank.v1beta1.SendEnabled) | repeated | | +| `default_send_enabled` | [bool](#bool) | | | - + -### SearchTxsResult -SearchTxsResult defines a structure for querying txs pageable +### SendEnabled +SendEnabled maps coin denom to a send_enabled status (whether a denom is +sendable). | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `total_count` | [uint64](#uint64) | | Count of all txs | -| `count` | [uint64](#uint64) | | Count of txs in current page | -| `page_number` | [uint64](#uint64) | | Index of current page, start from 1 | -| `page_total` | [uint64](#uint64) | | Count of total pages | -| `limit` | [uint64](#uint64) | | Max count txs per page | -| `txs` | [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | List of txs in current page | +| `denom` | [string](#string) | | | +| `enabled` | [bool](#bool) | | | - + -### SimulationResponse -SimulationResponse defines the response generated when a transaction is -successfully simulated. +### Supply +Supply represents a struct that passively keeps track of the total supply +amounts in the network. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `gas_info` | [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | | -| `result` | [Result](#cosmos.base.abci.v1beta1.Result) | | | +| `total` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | + - + -### StringEvent -StringEvent defines en Event object wrapper where all the attributes -contain key/value pairs that are strings instead of raw bytes. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `type` | [string](#string) | | | -| `attributes` | [Attribute](#cosmos.base.abci.v1beta1.Attribute) | repeated | | + +

      Top

      +## cosmos/bank/v1beta1/genesis.proto - + -### TxMsgData -TxMsgData defines a list of MsgData. A transaction will have a MsgData object -for each message. +### Balance +Balance defines an account address and balance pair used in the bank module's +genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | | +| `address` | [string](#string) | | address is the address of the balance holder. | +| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | coins defines the different coins this balance holds. | - + -### TxResponse -TxResponse defines a structure containing relevant tx data and metadata. The -tags are stringified and the log is JSON decoded. +### GenesisState +GenesisState defines the bank module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | The block height | -| `txhash` | [string](#string) | | The transaction hash. | -| `codespace` | [string](#string) | | Namespace for the Code | -| `code` | [uint32](#uint32) | | Response code. | -| `data` | [string](#string) | | Result bytes, if any. | -| `raw_log` | [string](#string) | | The output of the application's logger (raw string). May be non-deterministic. | -| `logs` | [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) | repeated | The output of the application's logger (typed). May be non-deterministic. | -| `info` | [string](#string) | | Additional information. May be non-deterministic. | -| `gas_wanted` | [int64](#int64) | | Amount of gas requested for transaction. | -| `gas_used` | [int64](#int64) | | Amount of gas consumed by transaction. | -| `tx` | [google.protobuf.Any](#google.protobuf.Any) | | The request transaction bytes. | -| `timestamp` | [string](#string) | | Time of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time. | +| `params` | [Params](#cosmos.bank.v1beta1.Params) | | params defines all the paramaters of the module. | +| `balances` | [Balance](#cosmos.bank.v1beta1.Balance) | repeated | balances is an array containing the balances of all the accounts. | +| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply represents the total supply. | +| `denom_metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | denom_metadata defines the metadata of the differents coins. | @@ -1725,6 +1755,327 @@ tags are stringified and the log is JSON decoded. + +

      Top

      + +## cosmos/bank/v1beta1/query.proto + + + + + +### QueryAllBalancesRequest +QueryBalanceRequest is the request type for the Query/AllBalances RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | address is the address to query balances for. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + + + + + + + + +### QueryAllBalancesResponse +QueryAllBalancesResponse is the response type for the Query/AllBalances RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `balances` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | balances is the balances of all the coins. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | + + + + + + + + +### QueryBalanceRequest +QueryBalanceRequest is the request type for the Query/Balance RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | address is the address to query balances for. | +| `denom` | [string](#string) | | denom is the coin denom to query balances for. | + + + + + + + + +### QueryBalanceResponse +QueryBalanceResponse is the response type for the Query/Balance RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | balance is the balance of the coin. | + + + + + + + + +### QueryDenomMetadataRequest +QueryDenomMetadataRequest is the request type for the Query/DenomMetadata RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `denom` | [string](#string) | | denom is the coin denom to query the metadata for. | + + + + + + + + +### QueryDenomMetadataResponse +QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | | metadata describes and provides all the client information for the requested token. | + + + + + + + + +### QueryDenomsMetadataRequest +QueryDenomsMetadataRequest is the request type for the Query/DenomsMetadata RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + + + + + + + + +### QueryDenomsMetadataResponse +QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `metadatas` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | metadata provides the client information for all the registered tokens. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | + + + + + + + + +### QueryParamsRequest +QueryParamsRequest defines the request type for querying x/bank parameters. + + + + + + + + +### QueryParamsResponse +QueryParamsResponse defines the response type for querying x/bank parameters. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params` | [Params](#cosmos.bank.v1beta1.Params) | | | + + + + + + + + +### QuerySupplyOfRequest +QuerySupplyOfRequest is the request type for the Query/SupplyOf RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `denom` | [string](#string) | | denom is the coin denom to query balances for. | + + + + + + + + +### QuerySupplyOfResponse +QuerySupplyOfResponse is the response type for the Query/SupplyOf RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | amount is the supply of the coin. | + + + + + + + + +### QueryTotalSupplyRequest +QueryTotalSupplyRequest is the request type for the Query/TotalSupply RPC +method. + + + + + + + + +### QueryTotalSupplyResponse +QueryTotalSupplyResponse is the response type for the Query/TotalSupply RPC +method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply is the supply of the coins | + + + + + + + + + + + + + + +### Query +Query defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Balance` | [QueryBalanceRequest](#cosmos.bank.v1beta1.QueryBalanceRequest) | [QueryBalanceResponse](#cosmos.bank.v1beta1.QueryBalanceResponse) | Balance queries the balance of a single coin for a single account. | GET|/cosmos/bank/v1beta1/balances/{address}/{denom}| +| `AllBalances` | [QueryAllBalancesRequest](#cosmos.bank.v1beta1.QueryAllBalancesRequest) | [QueryAllBalancesResponse](#cosmos.bank.v1beta1.QueryAllBalancesResponse) | AllBalances queries the balance of all coins for a single account. | GET|/cosmos/bank/v1beta1/balances/{address}| +| `TotalSupply` | [QueryTotalSupplyRequest](#cosmos.bank.v1beta1.QueryTotalSupplyRequest) | [QueryTotalSupplyResponse](#cosmos.bank.v1beta1.QueryTotalSupplyResponse) | TotalSupply queries the total supply of all coins. | GET|/cosmos/bank/v1beta1/supply| +| `SupplyOf` | [QuerySupplyOfRequest](#cosmos.bank.v1beta1.QuerySupplyOfRequest) | [QuerySupplyOfResponse](#cosmos.bank.v1beta1.QuerySupplyOfResponse) | SupplyOf queries the supply of a single coin. | GET|/cosmos/bank/v1beta1/supply/{denom}| +| `Params` | [QueryParamsRequest](#cosmos.bank.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.bank.v1beta1.QueryParamsResponse) | Params queries the parameters of x/bank module. | GET|/cosmos/bank/v1beta1/params| +| `DenomMetadata` | [QueryDenomMetadataRequest](#cosmos.bank.v1beta1.QueryDenomMetadataRequest) | [QueryDenomMetadataResponse](#cosmos.bank.v1beta1.QueryDenomMetadataResponse) | DenomsMetadata queries the client metadata of a given coin denomination. | GET|/cosmos/bank/v1beta1/denoms_metadata/{denom}| +| `DenomsMetadata` | [QueryDenomsMetadataRequest](#cosmos.bank.v1beta1.QueryDenomsMetadataRequest) | [QueryDenomsMetadataResponse](#cosmos.bank.v1beta1.QueryDenomsMetadataResponse) | DenomsMetadata queries the client metadata for all registered coin denominations. | GET|/cosmos/bank/v1beta1/denoms_metadata| + + + + + + +

      Top

      + +## cosmos/bank/v1beta1/tx.proto + + + + + +### MsgMultiSend +MsgMultiSend represents an arbitrary multi-in, multi-out send message. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `inputs` | [Input](#cosmos.bank.v1beta1.Input) | repeated | | +| `outputs` | [Output](#cosmos.bank.v1beta1.Output) | repeated | | + + + + + + + + +### MsgMultiSendResponse +MsgMultiSendResponse defines the Msg/MultiSend response type. + + + + + + + + +### MsgSend +MsgSend represents a message to send coins from one account to another. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `from_address` | [string](#string) | | | +| `to_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | + + + + + + + + +### MsgSendResponse +MsgSendResponse defines the Msg/Send response type. + + + + + + + + + + + + + + +### Msg +Msg defines the bank Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Send` | [MsgSend](#cosmos.bank.v1beta1.MsgSend) | [MsgSendResponse](#cosmos.bank.v1beta1.MsgSendResponse) | Send defines a method for sending coins from one account to another account. | | +| `MultiSend` | [MsgMultiSend](#cosmos.bank.v1beta1.MsgMultiSend) | [MsgMultiSendResponse](#cosmos.bank.v1beta1.MsgMultiSendResponse) | MultiSend defines a method for sending coins from some accounts to other accounts. | | + + + + +

      Top

      diff --git a/proto/cosmos/authz/v1beta1/authz.proto b/proto/cosmos/authz/v1beta1/authz.proto new file mode 100644 index 000000000000..56c403a79ff7 --- /dev/null +++ b/proto/cosmos/authz/v1beta1/authz.proto @@ -0,0 +1,37 @@ +syntax = "proto3"; +package cosmos.authz.v1beta1; + +import "cosmos/base/v1beta1/coin.proto"; +import "cosmos_proto/cosmos.proto"; +import "google/protobuf/timestamp.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/authz/types"; + +// SendAuthorization allows the grantee to spend up to spend_limit coins from +// the granter's account. +message SendAuthorization { + option (cosmos_proto.implements_interface) = "Authorization"; + + repeated cosmos.base.v1beta1.Coin spend_limit = 1 + [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; +} + +// GenericAuthorization gives the grantee unrestricted permissions to execute +// the provided method on behalf of the granter's account. +message GenericAuthorization { + option (cosmos_proto.implements_interface) = "Authorization"; + + // method name to grant unrestricted permissions to execute + // Note: MethodName() is already a method on `GenericAuthorization` type, + // we need some custom naming here so using `MessageName` + string method_name = 1 [(gogoproto.customname) = "MessageName"]; +} + +// AuthorizationGrant gives permissions to execute +// the provide method with expiration time. +message AuthorizationGrant { + google.protobuf.Any authorization = 1 [(cosmos_proto.accepts_interface) = "Authorization"]; + google.protobuf.Timestamp expiration = 2 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false]; +} diff --git a/proto/cosmos/authz/v1beta1/genesis.proto b/proto/cosmos/authz/v1beta1/genesis.proto new file mode 100644 index 000000000000..940d42e1f29b --- /dev/null +++ b/proto/cosmos/authz/v1beta1/genesis.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; +package cosmos.authz.v1beta1; + +import "google/protobuf/timestamp.proto"; +import "google/protobuf/any.proto"; +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; +import "cosmos/authz/v1beta1/tx.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/authz/types"; + +// GenesisState defines the authz module's genesis state. +message GenesisState { + repeated GrantAuthorization authorization = 1 [(gogoproto.nullable) = false]; +} + +// GrantAuthorization defines the GenesisState/GrantAuthorization type. +message GrantAuthorization { + string granter = 1; + string grantee = 2; + + google.protobuf.Any authorization = 3 [(cosmos_proto.accepts_interface) = "Authorization"]; + google.protobuf.Timestamp expiration = 4 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; +} diff --git a/proto/cosmos/authz/v1beta1/query.proto b/proto/cosmos/authz/v1beta1/query.proto new file mode 100644 index 000000000000..8c7d50a8d7e1 --- /dev/null +++ b/proto/cosmos/authz/v1beta1/query.proto @@ -0,0 +1,54 @@ +syntax = "proto3"; +package cosmos.authz.v1beta1; + +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; +import "google/api/annotations.proto"; +import "cosmos_proto/cosmos.proto"; +import "cosmos/base/query/v1beta1/pagination.proto"; +import "cosmos/authz/v1beta1/authz.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/authz/types"; + +// Query defines the gRPC querier service. +service Query { + // Returns any `Authorization` (or `nil`), with the expiration time, granted to the grantee by the granter for the + // provided msg type. + rpc Authorization(QueryAuthorizationRequest) returns (QueryAuthorizationResponse) { + option (google.api.http).get = "/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grant"; + } + + // Returns list of `Authorization`, granted to the grantee by the granter. + rpc Authorizations(QueryAuthorizationsRequest) returns (QueryAuthorizationsResponse) { + option (google.api.http).get = "/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grants"; + } +} + +// QueryAuthorizationRequest is the request type for the Query/Authorization RPC method. +message QueryAuthorizationRequest { + string granter = 1; + string grantee = 2; + string method_name = 3; +} + +// QueryAuthorizationResponse is the response type for the Query/Authorization RPC method. +message QueryAuthorizationResponse { + // authorization is a authorization granted for grantee by granter. + cosmos.authz.v1beta1.AuthorizationGrant authorization = 1; +} + +// QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. +message QueryAuthorizationsRequest { + string granter = 1; + string grantee = 2; + // pagination defines an pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 3; +} + +// QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. +message QueryAuthorizationsResponse { + // authorizations is a list of grants granted for grantee by granter. + repeated cosmos.authz.v1beta1.AuthorizationGrant authorizations = 1; + // pagination defines an pagination for the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} diff --git a/proto/cosmos/authz/v1beta1/tx.proto b/proto/cosmos/authz/v1beta1/tx.proto new file mode 100644 index 000000000000..69e3e6f1fba2 --- /dev/null +++ b/proto/cosmos/authz/v1beta1/tx.proto @@ -0,0 +1,62 @@ +syntax = "proto3"; +package cosmos.authz.v1beta1; + +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/any.proto"; +import "cosmos/base/abci/v1beta1/abci.proto"; +option go_package = "github.com/cosmos/cosmos-sdk/x/authz/types"; + +// Msg defines the authz Msg service. +service Msg { + // GrantAuthorization grants the provided authorization to the grantee on the granter's + // account with the provided expiration time. + rpc GrantAuthorization(MsgGrantAuthorizationRequest) returns (MsgGrantAuthorizationResponse); + + // ExecAuthorized attempts to execute the provided messages using + // authorizations granted to the grantee. Each message should have only + // one signer corresponding to the granter of the authorization. + rpc ExecAuthorized(MsgExecAuthorizedRequest) returns (MsgExecAuthorizedResponse); + + // RevokeAuthorization revokes any authorization corresponding to the provided method name on the + // granter's account that has been granted to the grantee. + rpc RevokeAuthorization(MsgRevokeAuthorizationRequest) returns (MsgRevokeAuthorizationResponse); +} + +// MsgGrantAuthorizationRequest grants the provided authorization to the grantee on the granter's +// account with the provided expiration time. +message MsgGrantAuthorizationRequest { + string granter = 1; + string grantee = 2; + + google.protobuf.Any authorization = 3 [(cosmos_proto.accepts_interface) = "Authorization"]; + google.protobuf.Timestamp expiration = 4 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; +} + +// MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse response type. +message MsgExecAuthorizedResponse { + cosmos.base.abci.v1beta1.Result result = 1; +} + +// MsgExecAuthorizedRequest attempts to execute the provided messages using +// authorizations granted to the grantee. Each message should have only +// one signer corresponding to the granter of the authorization. +message MsgExecAuthorizedRequest { + string grantee = 1; + repeated google.protobuf.Any msgs = 2; +} + +// MsgGrantAuthorizationResponse defines the Msg/MsgGrantAuthorization response type. +message MsgGrantAuthorizationResponse {} + +// MsgRevokeAuthorizationRequest revokes any authorization with the provided sdk.Msg type on the +// granter's account with that has been granted to the grantee. +message MsgRevokeAuthorizationRequest { + string granter = 1; + string grantee = 2; + string method_name = 3; +} + +// MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse response type. +message MsgRevokeAuthorizationResponse {} diff --git a/simapp/app.go b/simapp/app.go index b73538df032d..5e9c3e29e163 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -44,6 +44,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/capability" capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + "github.com/cosmos/cosmos-sdk/x/crisis" crisiskeeper "github.com/cosmos/cosmos-sdk/x/crisis/keeper" crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" @@ -87,6 +88,10 @@ import ( upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + authz "github.com/cosmos/cosmos-sdk/x/authz" + authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" + authztypes "github.com/cosmos/cosmos-sdk/x/authz/types" + // unnamed import of statik for swagger UI support _ "github.com/cosmos/cosmos-sdk/client/docs/statik" ) @@ -118,6 +123,7 @@ var ( upgrade.AppModuleBasic{}, evidence.AppModuleBasic{}, transfer.AppModuleBasic{}, + authz.AppModuleBasic{}, vesting.AppModuleBasic{}, ) @@ -171,6 +177,7 @@ type SimApp struct { CrisisKeeper crisiskeeper.Keeper UpgradeKeeper upgradekeeper.Keeper ParamsKeeper paramskeeper.Keeper + AuthzKeeper authzkeeper.Keeper IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly EvidenceKeeper evidencekeeper.Keeper TransferKeeper ibctransferkeeper.Keeper @@ -217,6 +224,7 @@ func NewSimApp( minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, + authztypes.StoreKey, ) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) @@ -282,6 +290,8 @@ func NewSimApp( appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, scopedIBCKeeper, ) + app.AuthzKeeper = authzkeeper.NewKeeper(keys[authztypes.StoreKey], appCodec, app.BaseApp.MsgServiceRouter()) + // register the proposal types govRouter := govtypes.NewRouter() govRouter.AddRoute(govtypes.RouterKey, govtypes.ProposalHandler). @@ -346,6 +356,7 @@ func NewSimApp( evidence.NewAppModule(app.EvidenceKeeper), ibc.NewAppModule(app.IBCKeeper), params.NewAppModule(app.ParamsKeeper), + authz.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), transferModule, ) @@ -367,7 +378,7 @@ func NewSimApp( app.mm.SetOrderInitGenesis( capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName, slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, crisistypes.ModuleName, - ibchost.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, ibctransfertypes.ModuleName, + ibchost.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, authztypes.ModuleName, ibctransfertypes.ModuleName, ) app.mm.RegisterInvariants(&app.CrisisKeeper) @@ -392,6 +403,7 @@ func NewSimApp( slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), params.NewAppModule(app.ParamsKeeper), evidence.NewAppModule(app.EvidenceKeeper), + authz.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), ibc.NewAppModule(app.IBCKeeper), transferModule, ) diff --git a/simapp/sim_test.go b/simapp/sim_test.go index cc1a7cada4f5..1c0609c1b82d 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -19,6 +19,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + authztypes "github.com/cosmos/cosmos-sdk/x/authz/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" @@ -177,6 +178,7 @@ func TestAppImportExport(t *testing.T) { {app.keys[capabilitytypes.StoreKey], newApp.keys[capabilitytypes.StoreKey], [][]byte{}}, {app.keys[ibchost.StoreKey], newApp.keys[ibchost.StoreKey], [][]byte{}}, {app.keys[ibctransfertypes.StoreKey], newApp.keys[ibctransfertypes.StoreKey], [][]byte{}}, + {app.keys[authztypes.StoreKey], newApp.keys[authztypes.StoreKey], [][]byte{}}, } for _, skp := range storeKeysPrefixes { diff --git a/types/errors/errors.go b/types/errors/errors.go index 1aa68816ccbf..6c540a1d6149 100644 --- a/types/errors/errors.go +++ b/types/errors/errors.go @@ -135,6 +135,9 @@ var ( // supported. ErrNotSupported = Register(RootCodespace, 37, "feature not supported") + // ErrNotFound defines an error when requested entity doesn't exist in the state. + ErrNotFound = Register(RootCodespace, 38, "not found") + // ErrPanic is only set when we recover from a panic, so we know to // redact potentially sensitive system info ErrPanic = Register(UndefinedCodespace, 111222, "panic") diff --git a/types/msgservice/service_msg_client.go b/types/msgservice/service_msg_client.go new file mode 100644 index 000000000000..de3be89094f8 --- /dev/null +++ b/types/msgservice/service_msg_client.go @@ -0,0 +1,50 @@ +package msgservice + +import ( + "context" + "fmt" + + gogogrpc "github.com/gogo/protobuf/grpc" + grpc "google.golang.org/grpc" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var _ gogogrpc.ClientConn = &ServiceMsgClientConn{} + +// ServiceMsgClientConn is an instance of grpc.ClientConn that is used to test building +// transactions with MsgClient's. It is intended to be replaced by the work in +// https://github.com/cosmos/cosmos-sdk/issues/7541 when that is ready. +type ServiceMsgClientConn struct { + msgs []sdk.Msg +} + +// Invoke implements the grpc ClientConn.Invoke method +func (t *ServiceMsgClientConn) Invoke(_ context.Context, method string, args, _ interface{}, _ ...grpc.CallOption) error { + req, ok := args.(sdk.MsgRequest) + if !ok { + return fmt.Errorf("%T should implement %T", args, (*sdk.MsgRequest)(nil)) + } + + err := req.ValidateBasic() + if err != nil { + return err + } + + t.msgs = append(t.msgs, sdk.ServiceMsg{ + MethodName: method, + Request: req, + }) + + return nil +} + +// NewStream implements the grpc ClientConn.NewStream method +func (t *ServiceMsgClientConn) NewStream(context.Context, *grpc.StreamDesc, string, ...grpc.CallOption) (grpc.ClientStream, error) { + return nil, fmt.Errorf("not supported") +} + +// GetMsgs returns ServiceMsgClientConn.msgs +func (t *ServiceMsgClientConn) GetMsgs() []sdk.Msg { + return t.msgs +} diff --git a/types/simulation/types.go b/types/simulation/types.go index f541b1d764de..46ede62a3536 100644 --- a/types/simulation/types.go +++ b/types/simulation/types.go @@ -2,7 +2,9 @@ package simulation import ( "encoding/json" + "fmt" "math/rand" + "reflect" "time" "github.com/cosmos/cosmos-sdk/baseapp" @@ -75,7 +77,16 @@ func NewOperationMsgBasic(route, name, comment string, ok bool, msg []byte) Oper } // NewOperationMsg - create a new operation message from sdk.Msg -func NewOperationMsg(msg sdk.Msg, ok bool, comment string) OperationMsg { +func NewOperationMsg(msg sdk.Msg, ok bool, comment string, cdc *codec.ProtoCodec) OperationMsg { + if reflect.TypeOf(msg) == reflect.TypeOf(sdk.ServiceMsg{}) { + srvMsg, ok := msg.(sdk.ServiceMsg) + if !ok { + panic(fmt.Sprintf("Expecting %T to implement sdk.ServiceMsg", msg)) + } + bz := cdc.MustMarshalJSON(srvMsg.Request) + + return NewOperationMsgBasic(srvMsg.MethodName, srvMsg.MethodName, comment, ok, bz) + } return NewOperationMsgBasic(msg.Route(), msg.Type(), comment, ok, msg.GetSignBytes()) } diff --git a/x/authz/client/cli/cli_test.go b/x/authz/client/cli/cli_test.go new file mode 100644 index 000000000000..fb6fb1a1774c --- /dev/null +++ b/x/authz/client/cli/cli_test.go @@ -0,0 +1,727 @@ +// +build norace + +package cli_test + +import ( + "fmt" + "strings" + "testing" + "time" + + "github.com/gogo/protobuf/proto" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + tmcli "github.com/tendermint/tendermint/libs/cli" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/testutil" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + "github.com/cosmos/cosmos-sdk/testutil/network" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz/client/cli" + govcli "github.com/cosmos/cosmos-sdk/x/gov/client/cli" + govtestutil "github.com/cosmos/cosmos-sdk/x/gov/client/testutil" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + "github.com/cosmos/cosmos-sdk/x/authz/types" + bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" + banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" +) + +type IntegrationTestSuite struct { + suite.Suite + + cfg network.Config + network *network.Network + grantee sdk.AccAddress +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + + s.cfg = cfg + s.network = network.New(s.T(), cfg) + + val := s.network.Validators[0] + + // Create new account in the keyring. + info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + s.Require().NoError(err) + newAddr := sdk.AccAddress(info.GetPubKey().Address()) + + // Send some funds to the new account. + _, err = banktestutil.MsgSendExec( + val.ClientCtx, + val.Address, + newAddr, + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + ) + s.Require().NoError(err) + s.grantee = newAddr + + // create a proposal with deposit + _, err = govtestutil.MsgSubmitProposal(val.ClientCtx, val.Address.String(), + "Text Proposal 1", "Where is the title!?", govtypes.ProposalTypeText, + fmt.Sprintf("--%s=%s", govcli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, govtypes.DefaultMinDepositTokens).String())) + s.Require().NoError(err) + + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +var typeMsgSend = types.SendAuthorization{}.MethodName() +var typeMsgVote = "/cosmos.gov.v1beta1.Msg/Vote" + +func (s *IntegrationTestSuite) TestQueryAuthorizations() { + val := s.network.Validators[0] + + grantee := s.grantee + twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() + + _, err := execGrantAuthorization( + val, + []string{ + grantee.String(), + "send", + fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + ) + s.Require().NoError(err) + + testCases := []struct { + name string + args []string + expectErr bool + expErrMsg string + }{ + { + "Error: Invalid grantee", + []string{ + val.Address.String(), + "invalid grantee", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + true, + "decoding bech32 failed: invalid character in string: ' '", + }, + { + "Error: Invalid granter", + []string{ + "invalid granter", + grantee.String(), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + true, + "decoding bech32 failed: invalid character in string: ' '", + }, + { + "Valid txn (json)", + []string{ + val.Address.String(), + grantee.String(), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + false, + ``, + }, + } + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryAuthorizations() + clientCtx := val.ClientCtx + resp, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Error(err) + s.Require().Contains(string(resp.Bytes()), tc.expErrMsg) + } else { + s.Require().NoError(err) + var grants types.QueryAuthorizationsResponse + err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &grants) + s.Require().NoError(err) + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryAuthorization() { + val := s.network.Validators[0] + + grantee := s.grantee + twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() + + _, err := execGrantAuthorization( + val, + []string{ + grantee.String(), + "send", + fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + ) + s.Require().NoError(err) + + testCases := []struct { + name string + args []string + expectErr bool + expectedOutput string + }{ + { + "Error: Invalid grantee", + []string{ + val.Address.String(), + "invalid grantee", + typeMsgSend, + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + true, + "", + }, + { + "Error: Invalid granter", + []string{ + "invalid granter", + grantee.String(), + typeMsgSend, + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + true, + "", + }, + { + "no authorization found", + []string{ + val.Address.String(), + grantee.String(), + "typeMsgSend", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + true, + "", + }, + { + "Valid txn (json)", + []string{ + val.Address.String(), + grantee.String(), + typeMsgSend, + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + false, + `{"@type":"/cosmos.authz.v1beta1.SendAuthorization","spend_limit":[{"denom":"steak","amount":"100"}]}`, + }, + } + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryAuthorization() + clientCtx := val.ClientCtx + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().Contains(strings.TrimSpace(out.String()), tc.expectedOutput) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() { + val := s.network.Validators[0] + grantee := s.grantee + + twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() + pastHour := time.Now().Add(time.Minute * time.Duration(-60)).Unix() + + testCases := []struct { + name string + args []string + respType proto.Message + expectedCode uint32 + expectErr bool + }{ + { + "Invalid granter Address", + []string{ + "grantee_addr", + "send", + fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit), + fmt.Sprintf("--%s=%s", flags.FlagFrom, "granter"), + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + }, + nil, + 0, + true, + }, + { + "Invalid grantee Address", + []string{ + "grantee_addr", + "send", + fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + }, + nil, 0, + true, + }, + { + "Invalid expiration time", + []string{ + grantee.String(), + "send", + fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, pastHour), + }, + nil, 0, + true, + }, + { + "fail with error invalid msg-type", + []string{ + grantee.String(), + "generic", + fmt.Sprintf("--%s=invalid-msg-type", cli.FlagMsgType), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + &sdk.TxResponse{}, 29, + false, + }, + { + "Valid tx send authorization", + []string{ + grantee.String(), + "send", + fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + &sdk.TxResponse{}, 0, + false, + }, + { + "Valid tx generic authorization", + []string{ + grantee.String(), + "generic", + fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + &sdk.TxResponse{}, 0, + false, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + clientCtx := val.ClientCtx + out, err := execGrantAuthorization( + val, + tc.args, + ) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func execGrantAuthorization(val *network.Validator, args []string) (testutil.BufferWriter, error) { + cmd := cli.NewCmdGrantAuthorization() + clientCtx := val.ClientCtx + return clitestutil.ExecTestCLICmd(clientCtx, cmd, args) +} + +func (s *IntegrationTestSuite) TestCmdRevokeAuthorizations() { + val := s.network.Validators[0] + + grantee := s.grantee + twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() + + // send-authorization + _, err := execGrantAuthorization( + val, + []string{ + grantee.String(), + "send", + fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + ) + s.Require().NoError(err) + + // generic-authorization + _, err = execGrantAuthorization( + val, + []string{ + grantee.String(), + "generic", + fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + ) + s.Require().NoError(err) + + testCases := []struct { + name string + args []string + respType proto.Message + expectedCode uint32 + expectErr bool + }{ + { + "invalid grantee address", + []string{ + "invlid grantee", + typeMsgSend, + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + }, + nil, + 0, + true, + }, + { + "invalid granter address", + []string{ + grantee.String(), + typeMsgSend, + fmt.Sprintf("--%s=%s", flags.FlagFrom, "granter"), + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + }, + nil, + 0, + true, + }, + { + "Valid tx send authorization", + []string{ + grantee.String(), + typeMsgSend, + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + &sdk.TxResponse{}, 0, + false, + }, + { + "Valid tx generic authorization", + []string{ + grantee.String(), + typeMsgVote, + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + &sdk.TxResponse{}, 0, + false, + }, + } + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.NewCmdRevokeAuthorization() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestExecAuthorizationWithExpiration() { + val := s.network.Validators[0] + grantee := s.grantee + tenSeconds := time.Now().Add(time.Second * time.Duration(10)).Unix() + + _, err := execGrantAuthorization( + val, + []string{ + grantee.String(), + "generic", + fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, tenSeconds), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + ) + s.Require().NoError(err) + // msg vote + voteTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.gov.v1beta1.Msg/Vote","proposal_id":"1","voter":"%s","option":"VOTE_OPTION_YES"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.Address.String()) + execMsg := testutil.WriteToNewTempFile(s.T(), voteTx) + + // waiting for authorization to expires + time.Sleep(12 * time.Second) + + cmd := cli.NewCmdExecAuthorization() + clientCtx := val.ClientCtx + + res, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, []string{ + execMsg.Name(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + }) + s.Require().NoError(err) + s.Require().Contains(res.String(), "authorization not found") +} + +func (s *IntegrationTestSuite) TestNewExecGenericAuthorized() { + val := s.network.Validators[0] + grantee := s.grantee + twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() + + _, err := execGrantAuthorization( + val, + []string{ + grantee.String(), + "generic", + fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + ) + s.Require().NoError(err) + + // msg vote + voteTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.gov.v1beta1.Msg/Vote","proposal_id":"1","voter":"%s","option":"VOTE_OPTION_YES"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.Address.String()) + execMsg := testutil.WriteToNewTempFile(s.T(), voteTx) + + testCases := []struct { + name string + args []string + respType proto.Message + expectedCode uint32 + expectErr bool + }{ + { + "fail invalid grantee", + []string{ + execMsg.Name(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, "grantee"), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + }, + nil, + 0, + true, + }, + { + "fail invalid json path", + []string{ + "/invalid/file.txt", + fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + }, + nil, + 0, + true, + }, + { + "valid txn", + []string{ + execMsg.Name(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + }, + &sdk.TxResponse{}, + 0, + false, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + + cmd := cli.NewCmdExecAuthorization() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestNewExecGrantAuthorized() { + val := s.network.Validators[0] + grantee := s.grantee + twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() + + _, err := execGrantAuthorization( + val, + []string{ + grantee.String(), + "send", + fmt.Sprintf("--%s=12%stoken", cli.FlagSpendLimit, val.Moniker), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + ) + s.Require().NoError(err) + tokens := sdk.NewCoins( + sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), sdk.NewInt(12)), + ) + normalGeneratedTx, err := bankcli.ServiceMsgSendExec( + val.ClientCtx, + val.Address, + grantee, + tokens, + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + ) + s.Require().NoError(err) + execMsg := testutil.WriteToNewTempFile(s.T(), normalGeneratedTx.String()) + testCases := []struct { + name string + args []string + respType proto.Message + expectedCode uint32 + expectErr bool + }{ + { + "fail invalid grantee", + []string{ + execMsg.Name(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, "grantee"), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + }, + nil, + 0, + true, + }, + { + "fail invalid json path", + []string{ + "/invalid/file.txt", + fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + }, + nil, + 0, + true, + }, + { + "valid txn", + []string{ + execMsg.Name(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + }, + &sdk.TxResponse{}, + 0, + false, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.NewCmdExecAuthorization() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/authz/client/cli/query.go b/x/authz/client/cli/query.go new file mode 100644 index 000000000000..ef7f326f71e7 --- /dev/null +++ b/x/authz/client/cli/query.go @@ -0,0 +1,138 @@ +package cli + +import ( + "context" + "fmt" + "strings" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +// GetQueryCmd returns the cli query commands for this module +func GetQueryCmd() *cobra.Command { + authorizationQueryCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Querying commands for the authz module", + Long: "", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + authorizationQueryCmd.AddCommand( + GetCmdQueryAuthorization(), + GetCmdQueryAuthorizations(), + ) + + return authorizationQueryCmd +} + +// GetCmdQueryAuthorizations implements the query authorizations command. +func GetCmdQueryAuthorizations() *cobra.Command { + cmd := &cobra.Command{ + Use: "authorizations [granter-addr] [grantee-addr]", + Args: cobra.ExactArgs(2), + Short: "query list of authorizations for a granter-grantee pair", + Long: strings.TrimSpace( + fmt.Sprintf(`Query list of authorizations for a granter-grantee pair: +Example: +$ %s query %s authorizations cosmos1skj.. cosmos1skjwj.. +`, version.AppName, types.ModuleName), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + granterAddr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + granteeAddr, err := sdk.AccAddressFromBech32(args[1]) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + res, err := queryClient.Authorizations( + context.Background(), + &types.QueryAuthorizationsRequest{ + Granter: granterAddr.String(), + Grantee: granteeAddr.String(), + Pagination: pageReq, + }, + ) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "authorizations") + return cmd +} + +// GetCmdQueryAuthorization implements the query authorization command. +func GetCmdQueryAuthorization() *cobra.Command { + cmd := &cobra.Command{ + Use: "authorization [granter-addr] [grantee-addr] [msg-type]", + Args: cobra.ExactArgs(3), + Short: "query authorization for a granter-grantee pair", + Long: strings.TrimSpace( + fmt.Sprintf(`Query authorization for a granter-grantee pair that matches the given msg-type: +Example: +$ %s query %s authorization cosmos1skjw.. cosmos1skjwj.. %s +`, version.AppName, types.ModuleName, types.SendAuthorization{}.MethodName()), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + granter, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + grantee, err := sdk.AccAddressFromBech32(args[1]) + if err != nil { + return err + } + + msgAuthorized := args[2] + + res, err := queryClient.Authorization( + context.Background(), + &types.QueryAuthorizationRequest{ + Granter: granter.String(), + Grantee: grantee.String(), + MethodName: msgAuthorized, + }, + ) + if err != nil { + return err + } + + return clientCtx.PrintProto(res.Authorization) + }, + } + flags.AddQueryFlagsToCmd(cmd) + return cmd +} diff --git a/x/authz/client/cli/tx.go b/x/authz/client/cli/tx.go new file mode 100644 index 000000000000..ba2fd210124b --- /dev/null +++ b/x/authz/client/cli/tx.go @@ -0,0 +1,222 @@ +package cli + +import ( + "context" + "errors" + "fmt" + "strings" + "time" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + "github.com/cosmos/cosmos-sdk/version" + authclient "github.com/cosmos/cosmos-sdk/x/auth/client" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +const FlagSpendLimit = "spend-limit" +const FlagMsgType = "msg-type" +const FlagExpiration = "expiration" + +// GetTxCmd returns the transaction commands for this module +func GetTxCmd() *cobra.Command { + AuthorizationTxCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Authorization transactions subcommands", + Long: "Authorize and revoke access to execute transactions on behalf of your address", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + AuthorizationTxCmd.AddCommand( + NewCmdGrantAuthorization(), + NewCmdRevokeAuthorization(), + NewCmdExecAuthorization(), + ) + + return AuthorizationTxCmd +} + +func NewCmdGrantAuthorization() *cobra.Command { + cmd := &cobra.Command{ + Use: "grant --from ", + Short: "Grant authorization to an address", + Long: strings.TrimSpace( + fmt.Sprintf(`Grant authorization to an address to execute a transaction on your behalf: + +Examples: + $ %s tx %s grant cosmos1skjw.. send %s --spend-limit=1000stake --from=cosmos1skl.. + $ %s tx %s grant cosmos1skjw.. generic --msg-type=/cosmos.gov.v1beta1.Msg/Vote --from=cosmos1sk.. + `, version.AppName, types.ModuleName, types.SendAuthorization{}.MethodName(), version.AppName, types.ModuleName), + ), + Args: cobra.RangeArgs(2, 3), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + grantee, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + var authorization types.Authorization + switch args[1] { + case "send": + limit, err := cmd.Flags().GetString(FlagSpendLimit) + if err != nil { + return err + } + + spendLimit, err := sdk.ParseCoinsNormalized(limit) + if err != nil { + return err + } + + if !spendLimit.IsAllPositive() { + return fmt.Errorf("spend-limit should be greater than zero") + } + + authorization = &types.SendAuthorization{ + SpendLimit: spendLimit, + } + case "generic": + msgType, err := cmd.Flags().GetString(FlagMsgType) + if err != nil { + return err + } + + authorization = types.NewGenericAuthorization(msgType) + default: + return fmt.Errorf("invalid authorization type, %s", args[1]) + } + + exp, err := cmd.Flags().GetInt64(FlagExpiration) + if err != nil { + return err + } + + msg, err := types.NewMsgGrantAuthorization(clientCtx.GetFromAddress(), grantee, authorization, time.Unix(exp, 0)) + if err != nil { + return err + } + + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + authzMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = authzMsgClient.GrantAuthorization(context.Background(), msg) + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) + }, + } + flags.AddTxFlagsToCmd(cmd) + cmd.Flags().String(FlagMsgType, "", "The Msg method name for which we are creating a GenericAuthorization") + cmd.Flags().String(FlagSpendLimit, "", "SpendLimit for Send Authorization, an array of Coins allowed spend") + cmd.Flags().Int64(FlagExpiration, time.Now().AddDate(1, 0, 0).Unix(), "The Unix timestamp. Default is one year.") + return cmd +} + +func NewCmdRevokeAuthorization() *cobra.Command { + cmd := &cobra.Command{ + Use: "revoke [grantee_address] [msg_type] --from=[granter_address]", + Short: "revoke authorization", + Long: strings.TrimSpace( + fmt.Sprintf(`revoke authorization from a granter to a grantee: +Example: + $ %s tx %s revoke cosmos1skj.. %s --from=cosmos1skj.. + `, version.AppName, types.ModuleName, types.SendAuthorization{}.MethodName()), + ), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + grantee, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + granter := clientCtx.GetFromAddress() + + msgAuthorized := args[1] + + msg := types.NewMsgRevokeAuthorization(granter, grantee, msgAuthorized) + + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + authzMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = authzMsgClient.RevokeAuthorization(context.Background(), &msg) + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) + }, + } + flags.AddTxFlagsToCmd(cmd) + return cmd +} + +func NewCmdExecAuthorization() *cobra.Command { + cmd := &cobra.Command{ + Use: "exec [msg_tx_json_file] --from [grantee]", + Short: "execute tx on behalf of granter account", + Long: strings.TrimSpace( + fmt.Sprintf(`execute tx on behalf of granter account: +Example: + $ %s tx %s exec tx.json --from grantee + $ %s tx bank send --from --chain-id --generate-only > tx.json && %s tx %s exec tx.json --from grantee + `, version.AppName, types.ModuleName, version.AppName, version.AppName, types.ModuleName), + ), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + grantee := clientCtx.GetFromAddress() + + if offline, _ := cmd.Flags().GetBool(flags.FlagOffline); offline { + return errors.New("cannot broadcast tx during offline mode") + } + + theTx, err := authclient.ReadTxFromFile(clientCtx, args[0]) + if err != nil { + return err + } + msgs := theTx.GetMsgs() + serviceMsgs := make([]sdk.ServiceMsg, len(msgs)) + for i, msg := range msgs { + srvMsg, ok := msg.(sdk.ServiceMsg) + if !ok { + return fmt.Errorf("tx contains %T which is not a sdk.ServiceMsg", msg) + } + serviceMsgs[i] = srvMsg + } + + msg := types.NewMsgExecAuthorized(grantee, serviceMsgs) + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + authzMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = authzMsgClient.ExecAuthorized(context.Background(), &msg) + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/authz/client/rest/grpc_query_test.go b/x/authz/client/rest/grpc_query_test.go new file mode 100644 index 000000000000..8ed8e857c6af --- /dev/null +++ b/x/authz/client/rest/grpc_query_test.go @@ -0,0 +1,235 @@ +// +build norace + +package rest_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/testutil/network" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/rest" + authztestutil "github.com/cosmos/cosmos-sdk/x/authz/client/testutil" + types "github.com/cosmos/cosmos-sdk/x/authz/types" + banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" +) + +type IntegrationTestSuite struct { + suite.Suite + cfg network.Config + network *network.Network + grantee sdk.AccAddress +} + +var typeMsgSend = types.SendAuthorization{}.MethodName() + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + cfg := network.DefaultConfig() + + cfg.NumValidators = 1 + s.cfg = cfg + s.network = network.New(s.T(), cfg) + + val := s.network.Validators[0] + // Create new account in the keyring. + info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + s.Require().NoError(err) + newAddr := sdk.AccAddress(info.GetPubKey().Address()) + + // Send some funds to the new account. + _, err = banktestutil.MsgSendExec( + val.ClientCtx, + val.Address, + newAddr, + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + ) + s.Require().NoError(err) + + // grant authorization + _, err = authztestutil.MsgGrantAuthorizationExec(val.ClientCtx, val.Address.String(), newAddr.String(), typeMsgSend, "100stake") + s.Require().NoError(err) + + s.grantee = newAddr + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +func (s *IntegrationTestSuite) TestQueryAuthorizationGRPC() { + val := s.network.Validators[0] + baseURL := val.APIAddress + testCases := []struct { + name string + url string + expectErr bool + errorMsg string + }{ + { + "fail invalid granter address", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?msg_type=%s", baseURL, "invalid_granter", s.grantee.String(), typeMsgSend), + true, + "decoding bech32 failed: invalid index of 1: invalid request", + }, + { + "fail invalid grantee address", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?msg_type=%s", baseURL, val.Address.String(), "invalid_grantee", typeMsgSend), + true, + "decoding bech32 failed: invalid index of 1: invalid request", + }, + { + "fail with empty granter", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?msg_type=%s", baseURL, "", s.grantee.String(), typeMsgSend), + true, + "Not Implemented", + }, + { + "fail with empty grantee", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?msg_type=%s", baseURL, val.Address.String(), "", typeMsgSend), + true, + "Not Implemented", + }, + { + "fail invalid msg-type", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?msg_type=%s", baseURL, val.Address.String(), s.grantee.String(), "invalidMsg"), + true, + "rpc error: code = NotFound desc = no authorization found for invalidMsg type: key not found", + }, + { + "valid query", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?msg_type=%s", baseURL, val.Address.String(), s.grantee.String(), typeMsgSend), + false, + "", + }, + } + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + resp, _ := rest.GetRequest(tc.url) + if tc.expectErr { + s.Require().Contains(string(resp), tc.errorMsg) + } else { + var authorization types.QueryAuthorizationResponse + err := val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, &authorization) + s.Require().NoError(err) + authorization.Authorization.UnpackInterfaces(val.ClientCtx.InterfaceRegistry) + auth := authorization.Authorization.GetAuthorizationGrant() + s.Require().Equal(auth.MethodName(), types.SendAuthorization{}.MethodName()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryAuthorizationsGRPC() { + val := s.network.Validators[0] + baseURL := val.APIAddress + testCases := []struct { + name string + url string + expectErr bool + errMsg string + preRun func() + postRun func(*types.QueryAuthorizationsResponse) + }{ + { + "fail invalid granter address", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grants", baseURL, "invalid_granter", s.grantee.String()), + true, + "decoding bech32 failed: invalid index of 1: invalid request", + func() {}, + func(_ *types.QueryAuthorizationsResponse) {}, + }, + { + "fail invalid grantee address", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grants", baseURL, val.Address.String(), "invalid_grantee"), + true, + "decoding bech32 failed: invalid index of 1: invalid request", + func() {}, + func(_ *types.QueryAuthorizationsResponse) {}, + }, + { + "fail empty grantee address", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grants", baseURL, "", "invalid_grantee"), + true, + "Not Implemented", + func() {}, + func(_ *types.QueryAuthorizationsResponse) {}, + }, + { + "valid query: expect single grant", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grants", baseURL, val.Address.String(), s.grantee.String()), + false, + "", + func() { + }, + func(authorizations *types.QueryAuthorizationsResponse) { + s.Require().Equal(len(authorizations.Authorizations), 1) + }, + }, + { + "valid query: expect two grants", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grants", baseURL, val.Address.String(), s.grantee.String()), + false, + "", + func() { + _, err := authztestutil.MsgGrantAuthorizationExec(val.ClientCtx, val.Address.String(), s.grantee.String(), "/cosmos.gov.v1beta1.Msg/Vote", "") + s.Require().NoError(err) + }, + func(authorizations *types.QueryAuthorizationsResponse) { + s.Require().Equal(len(authorizations.Authorizations), 2) + }, + }, + { + "valid query: expect single grant with pagination", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grants?pagination.limit=1", baseURL, val.Address.String(), s.grantee.String()), + false, + "", + func() {}, + func(authorizations *types.QueryAuthorizationsResponse) { + s.Require().Equal(len(authorizations.Authorizations), 1) + }, + }, + { + "valid query: expect two grants with pagination", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grants?pagination.limit=2", baseURL, val.Address.String(), s.grantee.String()), + false, + "", + func() {}, + func(authorizations *types.QueryAuthorizationsResponse) { + s.Require().Equal(len(authorizations.Authorizations), 2) + }, + }, + } + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + tc.preRun() + resp, _ := rest.GetRequest(tc.url) + if tc.expectErr { + s.Require().Contains(string(resp), tc.errMsg) + } else { + var authorizations types.QueryAuthorizationsResponse + err := val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, &authorizations) + s.Require().NoError(err) + tc.postRun(&authorizations) + } + + }) + } +} + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/authz/client/testutil/test_helpers.go b/x/authz/client/testutil/test_helpers.go new file mode 100644 index 000000000000..a56429a4d96a --- /dev/null +++ b/x/authz/client/testutil/test_helpers.go @@ -0,0 +1,34 @@ +package testutil + +import ( + "fmt" + "time" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/testutil" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + sdk "github.com/cosmos/cosmos-sdk/types" + authzcli "github.com/cosmos/cosmos-sdk/x/authz/client/cli" +) + +var commonArgs = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))).String()), +} + +func MsgGrantAuthorizationExec(clientCtx client.Context, granter, grantee, msgName, limit string, extraArgs ...string) (testutil.BufferWriter, error) { + args := []string{ + grantee, + msgName, + } + if limit != "" { + args = append(args, limit) + } + + args = append(args, fmt.Sprintf("--%s=%s", flags.FlagFrom, granter)) + args = append(args, fmt.Sprintf("--%s=%d", authzcli.FlagExpiration, time.Now().Add(time.Minute*time.Duration(120)).Unix())) + args = append(args, commonArgs...) + return clitestutil.ExecTestCLICmd(clientCtx, authzcli.NewCmdGrantAuthorization(), args) +} diff --git a/x/authz/exported/keeper.go b/x/authz/exported/keeper.go new file mode 100644 index 000000000000..9858ba821729 --- /dev/null +++ b/x/authz/exported/keeper.go @@ -0,0 +1,26 @@ +package exported + +import ( + "time" + + "github.com/cosmos/cosmos-sdk/x/authz/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type Keeper interface { + // DispatchActions executes the provided messages via authorization grants from the message signer to the grantee + DispatchActions(ctx sdk.Context, grantee sdk.AccAddress, msgs []sdk.ServiceMsg) sdk.Result + + // Grants the provided authorization to the grantee on the granter's account with the provided expiration time + // If there is an existing authorization grant for the same sdk.Msg type, this grant overwrites that. + Grant(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, authorization types.Authorization, expiration time.Time) error + + // Revokes any authorization for the provided message type granted to the grantee by the granter. + Revoke(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, msgType string) + + // Returns any Authorization (or nil), with the expiration time, + // granted to the grantee by the granter for the provided msg type. + // If the Authorization is expired already, it will revoke the authorization and return nil + GetOrRevokeAuthorization(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, msgType string) (cap types.Authorization, expiration time.Time) +} diff --git a/x/authz/genesis.go b/x/authz/genesis.go new file mode 100644 index 000000000000..e84ddf5987a0 --- /dev/null +++ b/x/authz/genesis.go @@ -0,0 +1,47 @@ +package authz + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz/keeper" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +// InitGenesis new authz genesis +func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, data *types.GenesisState) { + for _, entry := range data.Authorization { + grantee, err := sdk.AccAddressFromBech32(entry.Grantee) + if err != nil { + panic(err) + } + granter, err := sdk.AccAddressFromBech32(entry.Granter) + if err != nil { + panic(err) + } + authorization, ok := entry.Authorization.GetCachedValue().(types.Authorization) + if !ok { + panic("expected authorization") + } + + err = keeper.Grant(ctx, grantee, granter, authorization, entry.Expiration) + if err != nil { + panic(err) + } + } +} + +// ExportGenesis returns a GenesisState for a given context and keeper. +func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState { + var entries []types.GrantAuthorization + keeper.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, grant types.AuthorizationGrant) bool { + exp := grant.Expiration + entries = append(entries, types.GrantAuthorization{ + Granter: granter.String(), + Grantee: grantee.String(), + Expiration: exp, + Authorization: grant.Authorization, + }) + return false + }) + + return types.NewGenesisState(entries) +} diff --git a/x/authz/genesis_test.go b/x/authz/genesis_test.go new file mode 100644 index 000000000000..2d770d4c5210 --- /dev/null +++ b/x/authz/genesis_test.go @@ -0,0 +1,59 @@ +package authz_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" + authz "github.com/cosmos/cosmos-sdk/x/authz" + "github.com/cosmos/cosmos-sdk/x/authz/keeper" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +type GenesisTestSuite struct { + suite.Suite + + ctx sdk.Context + keeper keeper.Keeper +} + +func (suite *GenesisTestSuite) SetupTest() { + checkTx := false + app := simapp.Setup(checkTx) + + suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1}) + suite.keeper = app.AuthzKeeper +} + +var ( + granteePub = secp256k1.GenPrivKey().PubKey() + granterPub = secp256k1.GenPrivKey().PubKey() + granteeAddr = sdk.AccAddress(granteePub.Address()) + granterAddr = sdk.AccAddress(granterPub.Address()) +) + +func (suite *GenesisTestSuite) TestImportExportGenesis() { + coins := sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(1_000))) + + now := suite.ctx.BlockHeader().Time + grant := &types.SendAuthorization{SpendLimit: coins} + err := suite.keeper.Grant(suite.ctx, granteeAddr, granterAddr, grant, now.Add(time.Hour)) + suite.Require().NoError(err) + genesis := authz.ExportGenesis(suite.ctx, suite.keeper) + + // Clear keeper + suite.keeper.Revoke(suite.ctx, granteeAddr, granterAddr, grant.MethodName()) + + authz.InitGenesis(suite.ctx, suite.keeper, genesis) + newGenesis := authz.ExportGenesis(suite.ctx, suite.keeper) + suite.Require().Equal(genesis, newGenesis) +} + +func TestGenesisTestSuite(t *testing.T) { + suite.Run(t, new(GenesisTestSuite)) +} diff --git a/x/authz/keeper/grpc_query.go b/x/authz/keeper/grpc_query.go new file mode 100644 index 000000000000..7b1fcb1995dd --- /dev/null +++ b/x/authz/keeper/grpc_query.go @@ -0,0 +1,120 @@ +package keeper + +import ( + "context" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + proto "github.com/gogo/protobuf/proto" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +var _ types.QueryServer = Keeper{} + +// Authorizations implements the Query/Authorizations gRPC method. +func (k Keeper) Authorizations(c context.Context, req *types.QueryAuthorizationsRequest) (*types.QueryAuthorizationsResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + granter, err := sdk.AccAddressFromBech32(req.Granter) + + if err != nil { + return nil, err + } + grantee, err := sdk.AccAddressFromBech32(req.Grantee) + + if err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) + + store := ctx.KVStore(k.storeKey) + key := types.GetAuthorizationStoreKey(grantee, granter, "") + authStore := prefix.NewStore(store, key) + var authorizations []*types.AuthorizationGrant + pageRes, err := query.FilteredPaginate(authStore, req.Pagination, func(key []byte, value []byte, accumulate bool) (bool, error) { + auth, err := unmarshalAuthorization(k.cdc, value) + if err != nil { + return false, err + } + auth1 := auth.GetAuthorizationGrant() + if accumulate { + msg, ok := auth1.(proto.Message) + if !ok { + return false, status.Errorf(codes.Internal, "can't protomarshal %T", msg) + } + + authorizationAny, err := codectypes.NewAnyWithValue(msg) + if err != nil { + return false, status.Errorf(codes.Internal, err.Error()) + } + authorizations = append(authorizations, &types.AuthorizationGrant{ + Authorization: authorizationAny, + Expiration: auth.Expiration, + }) + } + return true, nil + }) + if err != nil { + return nil, err + } + + return &types.QueryAuthorizationsResponse{ + Authorizations: authorizations, + Pagination: pageRes, + }, nil +} + +// unmarshal an authorization from a store value +func unmarshalAuthorization(cdc codec.BinaryMarshaler, value []byte) (v types.AuthorizationGrant, err error) { + err = cdc.UnmarshalBinaryBare(value, &v) + return v, err +} + +// Authorization implements the Query/Authorization gRPC method. +func (k Keeper) Authorization(c context.Context, req *types.QueryAuthorizationRequest) (*types.QueryAuthorizationResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + if req.MethodName == "" { + return nil, status.Errorf(codes.InvalidArgument, "empty method-name") + } + + granter, err := sdk.AccAddressFromBech32(req.Granter) + + if err != nil { + return nil, err + } + grantee, err := sdk.AccAddressFromBech32(req.Grantee) + + if err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) + + authorization, expiration := k.GetOrRevokeAuthorization(ctx, grantee, granter, req.MethodName) + if authorization == nil { + return nil, status.Errorf(codes.NotFound, "no authorization found for %s type", req.MethodName) + } + + authorizationAny, err := codectypes.NewAnyWithValue(authorization) + if err != nil { + return nil, status.Errorf(codes.Internal, err.Error()) + } + + return &types.QueryAuthorizationResponse{ + Authorization: &types.AuthorizationGrant{ + Authorization: authorizationAny, + Expiration: expiration, + }, + }, nil +} diff --git a/x/authz/keeper/grpc_query_test.go b/x/authz/keeper/grpc_query_test.go new file mode 100644 index 000000000000..cc301fbca140 --- /dev/null +++ b/x/authz/keeper/grpc_query_test.go @@ -0,0 +1,157 @@ +package keeper_test + +import ( + gocontext "context" + "fmt" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +func (suite *TestSuite) TestGRPCQueryAuthorization() { + app, ctx, queryClient, addrs := suite.app, suite.ctx, suite.queryClient, suite.addrs + var ( + req *types.QueryAuthorizationRequest + expAuthorization types.Authorization + ) + testCases := []struct { + msg string + malleate func() + expPass bool + postTest func(res *types.QueryAuthorizationResponse) + }{ + { + "fail invalid granter addr", + func() { + req = &types.QueryAuthorizationRequest{} + }, + false, + func(res *types.QueryAuthorizationResponse) {}, + }, + { + "fail invalid grantee addr", + func() { + req = &types.QueryAuthorizationRequest{ + Granter: addrs[0].String(), + } + }, + false, + func(res *types.QueryAuthorizationResponse) {}, + }, + { + "fail invalid msg-type", + func() { + req = &types.QueryAuthorizationRequest{ + Granter: addrs[0].String(), + Grantee: addrs[1].String(), + } + }, + false, + func(res *types.QueryAuthorizationResponse) {}, + }, + { + "Success", + func() { + now := ctx.BlockHeader().Time + newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) + expAuthorization = &types.SendAuthorization{SpendLimit: newCoins} + err := app.AuthzKeeper.Grant(ctx, addrs[0], addrs[1], expAuthorization, now.Add(time.Hour)) + suite.Require().NoError(err) + req = &types.QueryAuthorizationRequest{ + Granter: addrs[1].String(), + Grantee: addrs[0].String(), + MethodName: expAuthorization.MethodName(), + } + }, + true, + func(res *types.QueryAuthorizationResponse) { + var auth types.Authorization + err := suite.app.InterfaceRegistry().UnpackAny(res.Authorization.Authorization, &auth) + suite.Require().NoError(err) + suite.Require().NotNil(auth) + suite.Require().Equal(auth.String(), expAuthorization.String()) + }, + }, + } + for _, testCase := range testCases { + suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() { + testCase.malleate() + result, err := queryClient.Authorization(gocontext.Background(), req) + if testCase.expPass { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + } + testCase.postTest(result) + }) + } +} + +func (suite *TestSuite) TestGRPCQueryAuthorizations() { + app, ctx, queryClient, addrs := suite.app, suite.ctx, suite.queryClient, suite.addrs + var ( + req *types.QueryAuthorizationsRequest + expAuthorization types.Authorization + ) + testCases := []struct { + msg string + malleate func() + expPass bool + postTest func(res *types.QueryAuthorizationsResponse) + }{ + { + "fail invalid granter addr", + func() { + req = &types.QueryAuthorizationsRequest{} + }, + false, + func(res *types.QueryAuthorizationsResponse) {}, + }, + { + "fail invalid grantee addr", + func() { + req = &types.QueryAuthorizationsRequest{ + Granter: addrs[0].String(), + } + }, + false, + func(res *types.QueryAuthorizationsResponse) {}, + }, + { + "Success", + func() { + now := ctx.BlockHeader().Time + newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) + expAuthorization = &types.SendAuthorization{SpendLimit: newCoins} + err := app.AuthzKeeper.Grant(ctx, addrs[0], addrs[1], expAuthorization, now.Add(time.Hour)) + suite.Require().NoError(err) + req = &types.QueryAuthorizationsRequest{ + Granter: addrs[1].String(), + Grantee: addrs[0].String(), + } + }, + true, + func(res *types.QueryAuthorizationsResponse) { + var auth types.Authorization + suite.Require().Equal(1, len(res.Authorizations)) + err := suite.app.InterfaceRegistry().UnpackAny(res.Authorizations[0].Authorization, &auth) + suite.Require().NoError(err) + suite.Require().NotNil(auth) + suite.Require().Equal(auth.String(), expAuthorization.String()) + }, + }, + } + for _, testCase := range testCases { + suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() { + testCase.malleate() + result, err := queryClient.Authorizations(gocontext.Background(), req) + if testCase.expPass { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + } + testCase.postTest(result) + }) + } +} diff --git a/x/authz/keeper/keeper.go b/x/authz/keeper/keeper.go new file mode 100644 index 000000000000..2888e17449b9 --- /dev/null +++ b/x/authz/keeper/keeper.go @@ -0,0 +1,210 @@ +package keeper + +import ( + "fmt" + "time" + + "github.com/gogo/protobuf/proto" + + "github.com/tendermint/tendermint/libs/log" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +type Keeper struct { + storeKey sdk.StoreKey + cdc codec.BinaryMarshaler + router *baseapp.MsgServiceRouter +} + +// NewKeeper constructs a message authorization Keeper +func NewKeeper(storeKey sdk.StoreKey, cdc codec.BinaryMarshaler, router *baseapp.MsgServiceRouter) Keeper { + return Keeper{ + storeKey: storeKey, + cdc: cdc, + router: router, + } +} + +// Logger returns a module-specific logger. +func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) +} + +// getAuthorizationGrant returns grant between granter and grantee for the given msg type +func (k Keeper) getAuthorizationGrant(ctx sdk.Context, grantStoreKey []byte) (grant types.AuthorizationGrant, found bool) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(grantStoreKey) + if bz == nil { + return grant, false + } + k.cdc.MustUnmarshalBinaryBare(bz, &grant) + return grant, true +} + +func (k Keeper) update(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, updated types.Authorization) error { + grantStoreKey := types.GetAuthorizationStoreKey(grantee, granter, updated.MethodName()) + grant, found := k.getAuthorizationGrant(ctx, grantStoreKey) + if !found { + return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "authorization not found") + } + + msg, ok := updated.(proto.Message) + if !ok { + sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", updated) + } + + any, err := codectypes.NewAnyWithValue(msg) + if err != nil { + return err + } + + grant.Authorization = any + store := ctx.KVStore(k.storeKey) + store.Set(grantStoreKey, k.cdc.MustMarshalBinaryBare(&grant)) + return nil +} + +// DispatchActions attempts to execute the provided messages via authorization +// grants from the message signer to the grantee. +func (k Keeper) DispatchActions(ctx sdk.Context, grantee sdk.AccAddress, serviceMsgs []sdk.ServiceMsg) (*sdk.Result, error) { + var msgResult *sdk.Result + var err error + for _, serviceMsg := range serviceMsgs { + signers := serviceMsg.GetSigners() + if len(signers) != 1 { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "authorization can be given to msg with only one signer") + } + granter := signers[0] + if !granter.Equals(grantee) { + authorization, _ := k.GetOrRevokeAuthorization(ctx, grantee, granter, serviceMsg.MethodName) + if authorization == nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "authorization not found") + } + allow, updated, del := authorization.Accept(serviceMsg, ctx.BlockHeader()) + if !allow { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, "requested amount is more than spend limit") + } + if del { + k.Revoke(ctx, grantee, granter, serviceMsg.Type()) + } else if updated != nil { + err = k.update(ctx, grantee, granter, updated) + if err != nil { + return nil, err + } + } + } + handler := k.router.Handler(serviceMsg.Route()) + + if handler == nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized message route: %s", serviceMsg.Route()) + } + + msgResult, err = handler(ctx, serviceMsg.Request) + if err != nil { + return nil, sdkerrors.Wrapf(err, "failed to execute message; message %s", serviceMsg.MethodName) + } + } + + return msgResult, nil +} + +// Grant method grants the provided authorization to the grantee on the granter's account with the provided expiration +// time. If there is an existing authorization grant for the same `sdk.Msg` type, this grant +// overwrites that. +func (k Keeper) Grant(ctx sdk.Context, grantee, granter sdk.AccAddress, authorization types.Authorization, expiration time.Time) error { + store := ctx.KVStore(k.storeKey) + + grant, err := types.NewAuthorizationGrant(authorization, expiration) + if err != nil { + return err + } + + bz := k.cdc.MustMarshalBinaryBare(&grant) + grantStoreKey := types.GetAuthorizationStoreKey(grantee, granter, authorization.MethodName()) + store.Set(grantStoreKey, bz) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventGrantAuthorization, + sdk.NewAttribute(types.AttributeKeyGrantType, authorization.MethodName()), + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(types.AttributeKeyGranterAddress, granter.String()), + sdk.NewAttribute(types.AttributeKeyGranteeAddress, grantee.String()), + ), + ) + return nil +} + +// Revoke method revokes any authorization for the provided message type granted to the grantee by the granter. +func (k Keeper) Revoke(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, msgType string) error { + store := ctx.KVStore(k.storeKey) + grantStoreKey := types.GetAuthorizationStoreKey(grantee, granter, msgType) + _, found := k.getAuthorizationGrant(ctx, grantStoreKey) + if !found { + return sdkerrors.Wrap(sdkerrors.ErrNotFound, "authorization not found") + } + store.Delete(grantStoreKey) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventRevokeAuthorization, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(types.AttributeKeyGrantType, msgType), + sdk.NewAttribute(types.AttributeKeyGranterAddress, granter.String()), + sdk.NewAttribute(types.AttributeKeyGranteeAddress, grantee.String()), + ), + ) + return nil +} + +// GetAuthorizations Returns list of `Authorizations` granted to the grantee by the granter. +func (k Keeper) GetAuthorizations(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress) (authorizations []types.Authorization) { + store := ctx.KVStore(k.storeKey) + key := types.GetAuthorizationStoreKey(grantee, granter, "") + iter := sdk.KVStorePrefixIterator(store, key) + defer iter.Close() + var authorization types.AuthorizationGrant + for ; iter.Valid(); iter.Next() { + k.cdc.MustUnmarshalBinaryBare(iter.Value(), &authorization) + authorizations = append(authorizations, authorization.GetAuthorizationGrant()) + } + return authorizations +} + +// GetOrRevokeAuthorization Returns any `Authorization` (or `nil`), with the expiration time, +// granted to the grantee by the granter for the provided msg type. +// If the Authorization is expired already, it will revoke the authorization and return nil +func (k Keeper) GetOrRevokeAuthorization(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, msgType string) (cap types.Authorization, expiration time.Time) { + grant, found := k.getAuthorizationGrant(ctx, types.GetAuthorizationStoreKey(grantee, granter, msgType)) + if !found { + return nil, time.Time{} + } + if grant.Expiration.Before(ctx.BlockHeader().Time) { + k.Revoke(ctx, grantee, granter, msgType) + return nil, time.Time{} + } + + return grant.GetAuthorizationGrant(), grant.Expiration +} + +// IterateGrants iterates over all authorization grants +func (k Keeper) IterateGrants(ctx sdk.Context, + handler func(granterAddr sdk.AccAddress, granteeAddr sdk.AccAddress, grant types.AuthorizationGrant) bool) { + store := ctx.KVStore(k.storeKey) + iter := sdk.KVStorePrefixIterator(store, types.GrantKey) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + var grant types.AuthorizationGrant + granterAddr, granteeAddr := types.ExtractAddressesFromGrantKey(iter.Key()) + k.cdc.MustUnmarshalBinaryBare(iter.Value(), &grant) + if handler(granterAddr, granteeAddr, grant) { + break + } + } +} diff --git a/x/authz/keeper/keeper_test.go b/x/authz/keeper/keeper_test.go new file mode 100644 index 000000000000..5a544a04af55 --- /dev/null +++ b/x/authz/keeper/keeper_test.go @@ -0,0 +1,218 @@ +package keeper_test + +import ( + "testing" + "time" + + "github.com/cosmos/cosmos-sdk/baseapp" + proto "github.com/gogo/protobuf/proto" + + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + tmtime "github.com/tendermint/tendermint/types/time" + + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/stretchr/testify/suite" +) + +type TestSuite struct { + suite.Suite + + app *simapp.SimApp + ctx sdk.Context + addrs []sdk.AccAddress + queryClient types.QueryClient +} + +func (s *TestSuite) SetupTest() { + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, tmproto.Header{}) + now := tmtime.Now() + ctx = ctx.WithBlockHeader(tmproto.Header{Time: now}) + queryHelper := baseapp.NewQueryServerTestHelper(ctx, app.InterfaceRegistry()) + types.RegisterQueryServer(queryHelper, app.AuthzKeeper) + queryClient := types.NewQueryClient(queryHelper) + s.queryClient = queryClient + + s.app = app + s.ctx = ctx + s.queryClient = queryClient + s.addrs = simapp.AddTestAddrsIncremental(app, ctx, 3, sdk.NewInt(30000000)) + +} + +func (s *TestSuite) TestKeeper() { + app, ctx, addrs := s.app, s.ctx, s.addrs + + granterAddr := addrs[0] + granteeAddr := addrs[1] + recipientAddr := addrs[2] + err := app.BankKeeper.SetBalances(ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000))) + s.Require().Nil(err) + s.Require().True(app.BankKeeper.GetBalance(ctx, granterAddr, "steak").IsEqual(sdk.NewCoin("steak", sdk.NewInt(10000)))) + + s.T().Log("verify that no authorization returns nil") + authorization, expiration := app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().Nil(authorization) + s.Require().Equal(expiration, time.Time{}) + now := s.ctx.BlockHeader().Time + s.Require().NotNil(now) + + newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) + s.T().Log("verify if expired authorization is rejected") + x := &types.SendAuthorization{SpendLimit: newCoins} + err = app.AuthzKeeper.Grant(ctx, granterAddr, granteeAddr, x, now.Add(-1*time.Hour)) + s.Require().NoError(err) + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().Nil(authorization) + + s.T().Log("verify if authorization is accepted") + x = &types.SendAuthorization{SpendLimit: newCoins} + err = app.AuthzKeeper.Grant(ctx, granteeAddr, granterAddr, x, now.Add(time.Hour)) + s.Require().NoError(err) + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().NotNil(authorization) + s.Require().Equal(authorization.MethodName(), types.SendAuthorization{}.MethodName()) + + s.T().Log("verify fetching authorization with wrong msg type fails") + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, proto.MessageName(&banktypes.MsgMultiSend{})) + s.Require().Nil(authorization) + + s.T().Log("verify fetching authorization with wrong grantee fails") + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, recipientAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().Nil(authorization) + + s.T().Log("verify revoke fails with wrong information") + err = app.AuthzKeeper.Revoke(ctx, recipientAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().Error(err) + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, recipientAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().Nil(authorization) + + s.T().Log("verify revoke executes with correct information") + err = app.AuthzKeeper.Revoke(ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().NoError(err) + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().Nil(authorization) + +} + +func (s *TestSuite) TestKeeperIter() { + app, ctx, addrs := s.app, s.ctx, s.addrs + + granterAddr := addrs[0] + granteeAddr := addrs[1] + + err := app.BankKeeper.SetBalances(ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000))) + s.Require().Nil(err) + s.Require().True(app.BankKeeper.GetBalance(ctx, granterAddr, "steak").IsEqual(sdk.NewCoin("steak", sdk.NewInt(10000)))) + + s.T().Log("verify that no authorization returns nil") + authorization, expiration := app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, "Abcd") + s.Require().Nil(authorization) + s.Require().Equal(time.Time{}, expiration) + now := s.ctx.BlockHeader().Time + s.Require().NotNil(now) + + newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) + s.T().Log("verify if expired authorization is rejected") + x := &types.SendAuthorization{SpendLimit: newCoins} + err = app.AuthzKeeper.Grant(ctx, granteeAddr, granterAddr, x, now.Add(-1*time.Hour)) + s.Require().NoError(err) + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, "abcd") + s.Require().Nil(authorization) + + app.AuthzKeeper.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, grant types.AuthorizationGrant) bool { + s.Require().Equal(granter, granterAddr) + s.Require().Equal(grantee, granteeAddr) + return true + }) + +} + +func (s *TestSuite) TestKeeperFees() { + app, addrs := s.app, s.addrs + + granterAddr := addrs[0] + granteeAddr := addrs[1] + recipientAddr := addrs[2] + err := app.BankKeeper.SetBalances(s.ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000))) + s.Require().Nil(err) + s.Require().True(app.BankKeeper.GetBalance(s.ctx, granterAddr, "steak").IsEqual(sdk.NewCoin("steak", sdk.NewInt(10000)))) + + now := s.ctx.BlockHeader().Time + s.Require().NotNil(now) + + smallCoin := sdk.NewCoins(sdk.NewInt64Coin("steak", 20)) + someCoin := sdk.NewCoins(sdk.NewInt64Coin("steak", 123)) + + msgs := types.NewMsgExecAuthorized(granteeAddr, []sdk.ServiceMsg{ + { + MethodName: types.SendAuthorization{}.MethodName(), + Request: &banktypes.MsgSend{ + Amount: sdk.NewCoins(sdk.NewInt64Coin("steak", 2)), + FromAddress: granterAddr.String(), + ToAddress: recipientAddr.String(), + }, + }, + }) + + s.Require().NoError(msgs.UnpackInterfaces(app.AppCodec())) + + s.T().Log("verify dispatch fails with invalid authorization") + executeMsgs, err := msgs.GetServiceMsgs() + s.Require().NoError(err) + result, err := app.AuthzKeeper.DispatchActions(s.ctx, granteeAddr, executeMsgs) + + s.Require().Nil(result) + s.Require().NotNil(err) + + s.T().Log("verify dispatch executes with correct information") + // grant authorization + err = app.AuthzKeeper.Grant(s.ctx, granteeAddr, granterAddr, &types.SendAuthorization{SpendLimit: smallCoin}, now) + s.Require().NoError(err) + authorization, _ := app.AuthzKeeper.GetOrRevokeAuthorization(s.ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().NotNil(authorization) + + s.Require().Equal(authorization.MethodName(), types.SendAuthorization{}.MethodName()) + + executeMsgs, err = msgs.GetServiceMsgs() + s.Require().NoError(err) + + result, err = app.AuthzKeeper.DispatchActions(s.ctx, granteeAddr, executeMsgs) + s.Require().NotNil(result) + s.Require().Nil(err) + + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(s.ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().NotNil(authorization) + + s.T().Log("verify dispatch fails with overlimit") + // grant authorization + + msgs = types.NewMsgExecAuthorized(granteeAddr, []sdk.ServiceMsg{ + { + MethodName: types.SendAuthorization{}.MethodName(), + Request: &banktypes.MsgSend{ + Amount: someCoin, + FromAddress: granterAddr.String(), + ToAddress: recipientAddr.String(), + }, + }, + }) + + s.Require().NoError(msgs.UnpackInterfaces(app.AppCodec())) + executeMsgs, err = msgs.GetServiceMsgs() + s.Require().NoError(err) + + result, err = app.AuthzKeeper.DispatchActions(s.ctx, granteeAddr, executeMsgs) + s.Require().Nil(result) + s.Require().NotNil(err) + + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(s.ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().NotNil(authorization) +} + +func TestTestSuite(t *testing.T) { + suite.Run(t, new(TestSuite)) +} diff --git a/x/authz/keeper/msg_server.go b/x/authz/keeper/msg_server.go new file mode 100644 index 000000000000..53beb129dfaa --- /dev/null +++ b/x/authz/keeper/msg_server.go @@ -0,0 +1,75 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +var _ types.MsgServer = Keeper{} + +// GrantAuthorization implements the MsgServer.GrantAuthorization method. +func (k Keeper) GrantAuthorization(goCtx context.Context, msg *types.MsgGrantAuthorizationRequest) (*types.MsgGrantAuthorizationResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + grantee, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + return nil, err + } + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + return nil, err + } + + authorization := msg.GetGrantAuthorization() + // If the granted service Msg doesn't exist, we throw an error. + if k.router.Handler(authorization.MethodName()) == nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "%s doesn't exist.", authorization.MethodName()) + } + + err = k.Grant(ctx, grantee, granter, authorization, msg.Expiration) + if err != nil { + return nil, err + } + + return &types.MsgGrantAuthorizationResponse{}, nil +} + +// RevokeAuthorization implements the MsgServer.RevokeAuthorization method. +func (k Keeper) RevokeAuthorization(goCtx context.Context, msg *types.MsgRevokeAuthorizationRequest) (*types.MsgRevokeAuthorizationResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + grantee, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + return nil, err + } + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + return nil, err + } + + err = k.Revoke(ctx, grantee, granter, msg.MethodName) + if err != nil { + return nil, err + } + + return &types.MsgRevokeAuthorizationResponse{}, nil +} + +// ExecAuthorized implements the MsgServer.ExecAuthorized method. +func (k Keeper) ExecAuthorized(goCtx context.Context, msg *types.MsgExecAuthorizedRequest) (*types.MsgExecAuthorizedResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + grantee, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + return nil, err + } + msgs, err := msg.GetServiceMsgs() + if err != nil { + return nil, err + } + result, err := k.DispatchActions(ctx, grantee, msgs) + if err != nil { + return nil, err + } + return &types.MsgExecAuthorizedResponse{Result: result}, nil +} diff --git a/x/authz/module.go b/x/authz/module.go new file mode 100644 index 000000000000..1bcd388e4df9 --- /dev/null +++ b/x/authz/module.go @@ -0,0 +1,194 @@ +package authz + +import ( + "context" + "encoding/json" + "math/rand" + + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + abci "github.com/tendermint/tendermint/abci/types" + + sdkclient "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/authz/keeper" + "github.com/cosmos/cosmos-sdk/x/authz/types" + + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + "github.com/cosmos/cosmos-sdk/x/authz/client/cli" + "github.com/cosmos/cosmos-sdk/x/authz/simulation" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} + _ module.AppModuleSimulation = AppModule{} +) + +// AppModuleBasic defines the basic application module used by the authz module. +type AppModuleBasic struct { + cdc codec.Marshaler +} + +// Name returns the authz module's name. +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterServices registers a gRPC query service to respond to the +// module-specific gRPC queries. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + types.RegisterMsgServer(cfg.MsgServer(), am.keeper) +} + +// RegisterLegacyAminoCodec registers the authz module's types for the given codec. +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {} + +// RegisterInterfaces registers the authz module's interface types +func (AppModuleBasic) RegisterInterfaces(registry cdctypes.InterfaceRegistry) { + types.RegisterInterfaces(registry) +} + +// DefaultGenesis returns default genesis state as raw bytes for the authz +// module. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONMarshaler) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesisState()) +} + +// ValidateGenesis performs genesis state validation for the authz module. +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONMarshaler, config sdkclient.TxEncodingConfig, bz json.RawMessage) error { + var data types.GenesisState + if err := cdc.UnmarshalJSON(bz, &data); err != nil { + return sdkerrors.Wrapf(err, "failed to unmarshal %s genesis state", types.ModuleName) + } + + return types.ValidateGenesis(data) +} + +// RegisterRESTRoutes registers the REST routes for the authz module. +func (AppModuleBasic) RegisterRESTRoutes(clientCtx sdkclient.Context, r *mux.Router) { +} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the authz module. +func (a AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx sdkclient.Context, mux *runtime.ServeMux) { + types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) +} + +// GetQueryCmd returns the cli query commands for the authz module +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() +} + +// GetTxCmd returns the transaction commands for the authz module +func (AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.GetTxCmd() +} + +// AppModule implements the sdk.AppModule interface +type AppModule struct { + AppModuleBasic + keeper keeper.Keeper + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper + registry cdctypes.InterfaceRegistry +} + +// NewAppModule creates a new AppModule object +func NewAppModule(cdc codec.Marshaler, keeper keeper.Keeper, ak types.AccountKeeper, bk types.BankKeeper, registry cdctypes.InterfaceRegistry) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{cdc: cdc}, + keeper: keeper, + accountKeeper: ak, + bankKeeper: bk, + registry: registry, + } +} + +// Name returns the authz module's name. +func (AppModule) Name() string { + return types.ModuleName +} + +// RegisterInvariants does nothing, there are no invariants to enforce +func (AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} + +// Route returns the message routing key for the staking module. +func (am AppModule) Route() sdk.Route { + return sdk.NewRoute(types.RouterKey, nil) +} + +func (am AppModule) NewHandler() sdk.Handler { + return nil +} + +// QuerierRoute returns the route we respond to for abci queries +func (AppModule) QuerierRoute() string { return "" } + +// LegacyQuerierHandler returns the authz module sdk.Querier. +func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier { + return nil +} + +// InitGenesis performs genesis initialization for the authz module. It returns +// no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONMarshaler, data json.RawMessage) []abci.ValidatorUpdate { + var genesisState types.GenesisState + cdc.MustUnmarshalJSON(data, &genesisState) + InitGenesis(ctx, am.keeper, &genesisState) + return []abci.ValidatorUpdate{} +} + +// ExportGenesis returns the exported genesis state as raw bytes for the authz +// module. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json.RawMessage { + gs := ExportGenesis(ctx, am.keeper) + return cdc.MustMarshalJSON(gs) +} + +func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {} + +// EndBlock does nothing +func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +// ____________________________________________________________________________ + +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenState of the authz module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + simulation.RandomizedGenState(simState) +} + +// ProposalContents returns all the authz content functions used to +// simulate governance proposals. +func (am AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent { + return nil +} + +// RandomizedParams creates randomized authz param changes for the simulator. +func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange { + return nil +} + +// RegisterStoreDecoder registers a decoder for authz module's types +func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { + sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) +} + +// WeightedOperations returns the all the gov module operations with their respective weights. +func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { + protoCdc := codec.NewProtoCodec(am.registry) + return simulation.WeightedOperations( + simState.AppParams, simState.Cdc, + am.accountKeeper, am.bankKeeper, am.keeper, am.cdc, protoCdc, + ) +} diff --git a/x/authz/simulation/decoder.go b/x/authz/simulation/decoder.go new file mode 100644 index 000000000000..c87f7a70c13a --- /dev/null +++ b/x/authz/simulation/decoder.go @@ -0,0 +1,26 @@ +package simulation + +import ( + "bytes" + "fmt" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/types/kv" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +// NewDecodeStore returns a decoder function closure that umarshals the KVPair's +// Value to the corresponding authz type. +func NewDecodeStore(cdc codec.Marshaler) func(kvA, kvB kv.Pair) string { + return func(kvA, kvB kv.Pair) string { + switch { + case bytes.Equal(kvA.Key[:1], types.GrantKey): + var grantA, grantB types.AuthorizationGrant + cdc.MustUnmarshalBinaryBare(kvA.Value, &grantA) + cdc.MustUnmarshalBinaryBare(kvB.Value, &grantB) + return fmt.Sprintf("%v\n%v", grantA, grantB) + default: + panic(fmt.Sprintf("invalid authz key %X", kvA.Key)) + } + } +} diff --git a/x/authz/simulation/decoder_test.go b/x/authz/simulation/decoder_test.go new file mode 100644 index 000000000000..86c2dfd6abb4 --- /dev/null +++ b/x/authz/simulation/decoder_test.go @@ -0,0 +1,50 @@ +package simulation_test + +import ( + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/kv" + "github.com/cosmos/cosmos-sdk/x/authz/simulation" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +func TestDecodeStore(t *testing.T) { + cdc := simapp.MakeTestEncodingConfig().Marshaler + dec := simulation.NewDecodeStore(cdc) + + grant, _ := types.NewAuthorizationGrant(types.NewSendAuthorization(sdk.NewCoins(sdk.NewInt64Coin("foo", 123))), time.Now().UTC()) + grantBz, err := cdc.MarshalBinaryBare(&grant) + require.NoError(t, err) + kvPairs := kv.Pairs{ + Pairs: []kv.Pair{ + {Key: []byte(types.GrantKey), Value: grantBz}, + {Key: []byte{0x99}, Value: []byte{0x99}}, + }, + } + + tests := []struct { + name string + expectedLog string + }{ + {"Grant", fmt.Sprintf("%v\n%v", grant, grant)}, + {"other", ""}, + } + + for i, tt := range tests { + i, tt := i, tt + t.Run(tt.name, func(t *testing.T) { + switch i { + case len(tests) - 1: + require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) + default: + require.Equal(t, tt.expectedLog, dec(kvPairs.Pairs[i], kvPairs.Pairs[i]), tt.name) + } + }) + } +} diff --git a/x/authz/simulation/genesis.go b/x/authz/simulation/genesis.go new file mode 100644 index 000000000000..ea674e24ea62 --- /dev/null +++ b/x/authz/simulation/genesis.go @@ -0,0 +1,38 @@ +package simulation + +import ( + "encoding/json" + "fmt" + "math/rand" + + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +// Simulation parameter constant. +const authz = "authz" + +// GenAuthorizationGrant returns an empty slice of authorization grants. +func GenAuthorizationGrant(_ *rand.Rand, _ []simtypes.Account) []types.GrantAuthorization { + return []types.GrantAuthorization{} +} + +// RandomizedGenState generates a random GenesisState for authz. +func RandomizedGenState(simState *module.SimulationState) { + var grants []types.GrantAuthorization + + simState.AppParams.GetOrGenerate( + simState.Cdc, authz, &grants, simState.Rand, + func(r *rand.Rand) { grants = GenAuthorizationGrant(r, simState.Accounts) }, + ) + authzGrantsGenesis := types.NewGenesisState(grants) + + bz, err := json.MarshalIndent(&authzGrantsGenesis, "", " ") + if err != nil { + panic(err) + } + + fmt.Printf("Selected randomly generated %s parameters:\n%s\n", types.ModuleName, bz) + simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(authzGrantsGenesis) +} diff --git a/x/authz/simulation/genesis_test.go b/x/authz/simulation/genesis_test.go new file mode 100644 index 000000000000..4672d195ec0a --- /dev/null +++ b/x/authz/simulation/genesis_test.go @@ -0,0 +1,40 @@ +package simulation_test + +import ( + "encoding/json" + "math/rand" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/authz/simulation" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +func TestRandomizedGenState(t *testing.T) { + interfaceRegistry := codectypes.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + s := rand.NewSource(1) + r := rand.New(s) + + simState := module.SimulationState{ + AppParams: make(simtypes.AppParams), + Cdc: cdc, + Rand: r, + NumBonded: 3, + Accounts: simtypes.RandomAccounts(r, 3), + InitialStake: 1000, + GenState: make(map[string]json.RawMessage), + } + + simulation.RandomizedGenState(&simState) + var authzGenesis types.GenesisState + simState.Cdc.MustUnmarshalJSON(simState.GenState[types.ModuleName], &authzGenesis) + + require.Len(t, authzGenesis.Authorization, 0) +} diff --git a/x/authz/simulation/operations.go b/x/authz/simulation/operations.go new file mode 100644 index 000000000000..5533d9fa6916 --- /dev/null +++ b/x/authz/simulation/operations.go @@ -0,0 +1,291 @@ +package simulation + +import ( + "context" + "math/rand" + "strings" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/simapp/helpers" + simappparams "github.com/cosmos/cosmos-sdk/simapp/params" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/authz/keeper" + "github.com/cosmos/cosmos-sdk/x/authz/types" + banktype "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/simulation" +) + +// authz message types +const ( + TypeMsgGrantAuthorization = "/cosmos.authz.v1beta1.Msg/GrantAuthorization" + TypeMsgRevokeAuthorization = "/cosmos.authz.v1beta1.Msg/RevokeAuthorization" + TypeMsgExecDelegated = "/cosmos.authz.v1beta1.Msg/ExecAuthorized" +) + +// Simulation operation weights constants +const ( + OpWeightMsgGrantAuthorization = "op_weight_msg_grant_authorization" + OpWeightRevokeAuthorization = "op_weight_msg_revoke_authorization" + OpWeightExecAuthorized = "op_weight_msg_execute_authorized" +) + +// WeightedOperations returns all the operations from the module with their respective weights +func WeightedOperations( + appParams simtypes.AppParams, cdc codec.JSONMarshaler, ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, appCdc cdctypes.AnyUnpacker, protoCdc *codec.ProtoCodec) simulation.WeightedOperations { + + var ( + weightMsgGrantAuthorization int + weightRevokeAuthorization int + weightExecAuthorized int + ) + + appParams.GetOrGenerate(cdc, OpWeightMsgGrantAuthorization, &weightMsgGrantAuthorization, nil, + func(_ *rand.Rand) { + weightMsgGrantAuthorization = simappparams.DefaultWeightMsgDelegate + }, + ) + + appParams.GetOrGenerate(cdc, OpWeightRevokeAuthorization, &weightRevokeAuthorization, nil, + func(_ *rand.Rand) { + weightRevokeAuthorization = simappparams.DefaultWeightMsgUndelegate + }, + ) + + appParams.GetOrGenerate(cdc, OpWeightExecAuthorized, &weightExecAuthorized, nil, + func(_ *rand.Rand) { + weightExecAuthorized = simappparams.DefaultWeightMsgSend + }, + ) + + return simulation.WeightedOperations{ + simulation.NewWeightedOperation( + weightMsgGrantAuthorization, + SimulateMsgGrantAuthorization(ak, bk, k, protoCdc), + ), + simulation.NewWeightedOperation( + weightRevokeAuthorization, + SimulateMsgRevokeAuthorization(ak, bk, k, protoCdc), + ), + simulation.NewWeightedOperation( + weightExecAuthorized, + SimulateMsgExecuteAuthorized(ak, bk, k, appCdc, protoCdc), + ), + } +} + +// SimulateMsgGrantAuthorization generates a MsgGrantAuthorization with random values. +// nolint: funlen +func SimulateMsgGrantAuthorization(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, + protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + granter := accs[0] + grantee := accs[1] + + account := ak.GetAccount(ctx, granter.Address) + + spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, ctx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgGrantAuthorization, err.Error()), nil, err + } + + blockTime := ctx.BlockTime() + msg, err := types.NewMsgGrantAuthorization(granter.Address, grantee.Address, + types.NewSendAuthorization(spendableCoins.Sub(fees)), blockTime.AddDate(1, 0, 0)) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgGrantAuthorization, err.Error()), nil, err + } + txGen := simappparams.MakeTestEncodingConfig().TxConfig + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + authzMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = authzMsgClient.GrantAuthorization(context.Background(), msg) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgGrantAuthorization, err.Error()), nil, err + } + tx, err := helpers.GenTx( + txGen, + svcMsgClientConn.GetMsgs(), + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + granter.PrivKey, + ) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgGrantAuthorization, "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, svcMsgClientConn.GetMsgs()[0].Type(), "unable to deliver tx"), nil, err + } + return simtypes.NewOperationMsg(svcMsgClientConn.GetMsgs()[0], true, "", protoCdc), nil, err + } +} + +// SimulateMsgRevokeAuthorization generates a MsgRevokeAuthorization with random values. +// nolint: funlen +func SimulateMsgRevokeAuthorization(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + hasGrant := false + var targetGrant types.AuthorizationGrant + var granterAddr sdk.AccAddress + var granteeAddr sdk.AccAddress + k.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, grant types.AuthorizationGrant) bool { + targetGrant = grant + granterAddr = granter + granteeAddr = grantee + hasGrant = true + return true + }) + + if !hasGrant { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeAuthorization, "no grants"), nil, nil + } + + granter, ok := simtypes.FindAccount(accs, granterAddr) + if !ok { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeAuthorization, "Account not found"), nil, nil + } + account := ak.GetAccount(ctx, granter.Address) + + spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, ctx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeAuthorization, "fee error"), nil, err + } + auth := targetGrant.GetAuthorizationGrant() + msg := types.NewMsgRevokeAuthorization(granterAddr, granteeAddr, auth.MethodName()) + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + authzMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = authzMsgClient.RevokeAuthorization(context.Background(), &msg) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeAuthorization, err.Error()), nil, err + } + tx, err := helpers.GenTx( + txGen, + svcMsgClientConn.GetMsgs(), + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + granter.PrivKey, + ) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeAuthorization, err.Error()), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + return simtypes.NewOperationMsg(svcMsgClientConn.GetMsgs()[0], true, "", protoCdc), nil, err + } +} + +// SimulateMsgExecuteAuthorized generates a MsgExecuteAuthorized with random values. +// nolint: funlen +func SimulateMsgExecuteAuthorized(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, cdc cdctypes.AnyUnpacker, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + hasGrant := false + var targetGrant types.AuthorizationGrant + var granterAddr sdk.AccAddress + var granteeAddr sdk.AccAddress + k.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, grant types.AuthorizationGrant) bool { + targetGrant = grant + granterAddr = granter + granteeAddr = grantee + hasGrant = true + return true + }) + + if !hasGrant { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, "Not found"), nil, nil + } + + grantee, _ := simtypes.FindAccount(accs, granteeAddr) + granterAccount := ak.GetAccount(ctx, granterAddr) + granteeAccount := ak.GetAccount(ctx, granteeAddr) + + granterspendableCoins := bk.SpendableCoins(ctx, granterAccount.GetAddress()) + if granterspendableCoins.Empty() { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, "no coins"), nil, nil + } + + if targetGrant.Expiration.Before(ctx.BlockHeader().Time) { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, "grant expired"), nil, nil + } + + granteespendableCoins := bk.SpendableCoins(ctx, granteeAccount.GetAddress()) + fees, err := simtypes.RandomFees(r, ctx, granteespendableCoins) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, "fee error"), nil, err + } + sendCoins := sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(10))) + + execMsg := sdk.ServiceMsg{ + MethodName: types.SendAuthorization{}.MethodName(), + Request: banktype.NewMsgSend( + granterAddr, + granteeAddr, + sendCoins, + ), + } + + msg := types.NewMsgExecAuthorized(grantee.Address, []sdk.ServiceMsg{execMsg}) + sendGrant := targetGrant.Authorization.GetCachedValue().(*types.SendAuthorization) + allow, _, _ := sendGrant.Accept(execMsg, ctx.BlockHeader()) + if !allow { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, "not allowed"), nil, nil + } + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + authzMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = authzMsgClient.ExecAuthorized(context.Background(), &msg) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, err.Error()), nil, err + } + tx, err := helpers.GenTx( + txGen, + svcMsgClientConn.GetMsgs(), + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{granteeAccount.GetAccountNumber()}, + []uint64{granteeAccount.GetSequence()}, + grantee.PrivKey, + ) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, err.Error()), nil, err + } + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + if strings.Contains(err.Error(), "insufficient fee") { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, "insufficient fee"), nil, nil + } + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, err.Error()), nil, err + } + msg.UnpackInterfaces(cdc) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, "unmarshal error"), nil, err + } + return simtypes.NewOperationMsg(svcMsgClientConn.GetMsgs()[0], true, "success", protoCdc), nil, nil + } +} diff --git a/x/authz/simulation/operations_test.go b/x/authz/simulation/operations_test.go new file mode 100644 index 000000000000..83be182df746 --- /dev/null +++ b/x/authz/simulation/operations_test.go @@ -0,0 +1,197 @@ +package simulation_test + +import ( + "math/rand" + "testing" + "time" + + "github.com/stretchr/testify/suite" + + abci "github.com/tendermint/tendermint/abci/types" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simapp" + simappparams "github.com/cosmos/cosmos-sdk/simapp/params" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/authz/simulation" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +type SimTestSuite struct { + suite.Suite + + ctx sdk.Context + app *simapp.SimApp + protoCdc *codec.ProtoCodec +} + +func (suite *SimTestSuite) SetupTest() { + checkTx := false + app := simapp.Setup(checkTx) + suite.app = app + suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{}) + suite.protoCdc = codec.NewProtoCodec(suite.app.InterfaceRegistry()) +} + +func (suite *SimTestSuite) TestWeightedOperations() { + cdc := suite.app.AppCodec() + appParams := make(simtypes.AppParams) + + weightesOps := simulation.WeightedOperations(appParams, cdc, suite.app.AccountKeeper, + suite.app.BankKeeper, suite.app.AuthzKeeper, cdc, suite.protoCdc, + ) + + // setup 3 accounts + s := rand.NewSource(1) + r := rand.New(s) + accs := suite.getTestingAccounts(r, 3) + + expected := []struct { + weight int + opMsgRoute string + opMsgName string + }{ + {simappparams.DefaultWeightMsgDelegate, types.ModuleName, simulation.TypeMsgGrantAuthorization}, + {simappparams.DefaultWeightMsgUndelegate, types.ModuleName, simulation.TypeMsgRevokeAuthorization}, + {simappparams.DefaultWeightMsgSend, types.ModuleName, simulation.TypeMsgExecDelegated}, + } + + for i, w := range weightesOps { + operationMsg, _, _ := w.Op()(r, suite.app.BaseApp, suite.ctx, accs, "") + // the following checks are very much dependent from the ordering of the output given + // by WeightedOperations. if the ordering in WeightedOperations changes some tests + // will fail + suite.Require().Equal(expected[i].weight, w.Weight(), "weight should be the same") + suite.Require().Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") + suite.Require().Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") + } +} + +func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { + accounts := simtypes.RandomAccounts(r, n) + + initAmt := sdk.TokensFromConsensusPower(200000) + initCoins := sdk.NewCoins(sdk.NewCoin("foo", initAmt)) + + // add coins to the accounts + for _, account := range accounts { + acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, account.Address) + suite.app.AccountKeeper.SetAccount(suite.ctx, acc) + err := suite.app.BankKeeper.SetBalances(suite.ctx, account.Address, initCoins) + suite.Require().NoError(err) + } + + return accounts +} + +func (suite *SimTestSuite) TestSimulateGrantAuthorization() { + // setup 3 accounts + s := rand.NewSource(1) + r := rand.New(s) + accounts := suite.getTestingAccounts(r, 2) + blockTime := time.Now().UTC() + ctx := suite.ctx.WithBlockTime(blockTime) + + // begin a new block + suite.app.BeginBlock(abci.RequestBeginBlock{ + Header: tmproto.Header{ + Height: suite.app.LastBlockHeight() + 1, + AppHash: suite.app.LastCommitID().Hash, + }, + }) + + granter := accounts[0] + grantee := accounts[1] + + // execute operation + op := simulation.SimulateMsgGrantAuthorization(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.AuthzKeeper, suite.protoCdc) + operationMsg, futureOperations, err := op(r, suite.app.BaseApp, ctx, accounts, "") + suite.Require().NoError(err) + + var msg types.MsgGrantAuthorizationRequest + suite.app.AppCodec().UnmarshalJSON(operationMsg.Msg, &msg) + suite.Require().True(operationMsg.OK) + suite.Require().Equal(granter.Address.String(), msg.Granter) + suite.Require().Equal(grantee.Address.String(), msg.Grantee) + suite.Require().Len(futureOperations, 0) + +} + +func (suite *SimTestSuite) TestSimulateRevokeAuthorization() { + // setup 3 accounts + s := rand.NewSource(1) + r := rand.New(s) + accounts := suite.getTestingAccounts(r, 3) + + // begin a new block + suite.app.BeginBlock(abci.RequestBeginBlock{ + Header: tmproto.Header{ + Height: suite.app.LastBlockHeight() + 1, + AppHash: suite.app.LastCommitID().Hash, + }}) + + initAmt := sdk.TokensFromConsensusPower(200000) + initCoins := sdk.NewCoins(sdk.NewCoin("foo", initAmt)) + + granter := accounts[0] + grantee := accounts[1] + authorization := types.NewSendAuthorization(initCoins) + + err := suite.app.AuthzKeeper.Grant(suite.ctx, grantee.Address, granter.Address, authorization, time.Now().Add(30*time.Hour)) + suite.Require().NoError(err) + + // execute operation + op := simulation.SimulateMsgRevokeAuthorization(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.AuthzKeeper, suite.protoCdc) + operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") + suite.Require().NoError(err) + + var msg types.MsgRevokeAuthorizationRequest + suite.app.AppCodec().UnmarshalJSON(operationMsg.Msg, &msg) + + suite.Require().True(operationMsg.OK) + suite.Require().Equal(granter.Address.String(), msg.Granter) + suite.Require().Equal(grantee.Address.String(), msg.Grantee) + suite.Require().Equal(types.SendAuthorization{}.MethodName(), msg.MethodName) + suite.Require().Len(futureOperations, 0) + +} + +func (suite *SimTestSuite) TestSimulateExecAuthorization() { + // setup 3 accounts + s := rand.NewSource(1) + r := rand.New(s) + accounts := suite.getTestingAccounts(r, 3) + + // begin a new block + suite.app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: suite.app.LastBlockHeight() + 1, AppHash: suite.app.LastCommitID().Hash}}) + + initAmt := sdk.TokensFromConsensusPower(200000) + initCoins := sdk.NewCoins(sdk.NewCoin("foo", initAmt)) + + granter := accounts[0] + grantee := accounts[1] + authorization := types.NewSendAuthorization(initCoins) + + err := suite.app.AuthzKeeper.Grant(suite.ctx, grantee.Address, granter.Address, authorization, time.Now().Add(30*time.Hour)) + suite.Require().NoError(err) + + // execute operation + op := simulation.SimulateMsgExecuteAuthorized(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.AuthzKeeper, suite.app.AppCodec(), suite.protoCdc) + operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") + suite.Require().NoError(err) + + var msg types.MsgExecAuthorizedRequest + + suite.app.AppCodec().UnmarshalJSON(operationMsg.Msg, &msg) + + suite.Require().True(operationMsg.OK) + suite.Require().Equal(grantee.Address.String(), msg.Grantee) + suite.Require().Len(futureOperations, 0) + +} + +func TestSimTestSuite(t *testing.T) { + suite.Run(t, new(SimTestSuite)) +} diff --git a/x/authz/types/authorizations.go b/x/authz/types/authorizations.go new file mode 100644 index 000000000000..18533fe07201 --- /dev/null +++ b/x/authz/types/authorizations.go @@ -0,0 +1,63 @@ +package types + +import ( + "time" + + "github.com/gogo/protobuf/proto" + + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +type Authorization interface { + proto.Message + + // MethodName returns the fully-qualified Msg service method name as described in ADR 031. + MethodName() string + + // Accept determines whether this grant permits the provided sdk.ServiceMsg to be performed, and if + // so provides an upgraded authorization instance. + Accept(msg sdk.ServiceMsg, block tmproto.Header) (allow bool, updated Authorization, delete bool) +} + +// NewAuthorizationGrant returns new AuthrizationGrant +func NewAuthorizationGrant(authorization Authorization, expiration time.Time) (AuthorizationGrant, error) { + auth := AuthorizationGrant{ + Expiration: expiration, + } + msg, ok := authorization.(proto.Message) + if !ok { + return AuthorizationGrant{}, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", authorization) + } + + any, err := types.NewAnyWithValue(msg) + if err != nil { + return AuthorizationGrant{}, err + } + + auth.Authorization = any + + return auth, nil +} + +var ( + _ types.UnpackInterfacesMessage = &AuthorizationGrant{} +) + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (auth AuthorizationGrant) UnpackInterfaces(unpacker types.AnyUnpacker) error { + var authorization Authorization + return unpacker.UnpackAny(auth.Authorization, &authorization) +} + +// GetAuthorizationGrant returns the cached value from the AuthorizationGrant.Authorization if present. +func (auth AuthorizationGrant) GetAuthorizationGrant() Authorization { + authorization, ok := auth.Authorization.GetCachedValue().(Authorization) + if !ok { + return nil + } + return authorization +} diff --git a/x/authz/types/authz.pb.go b/x/authz/types/authz.pb.go new file mode 100644 index 000000000000..3343083205f5 --- /dev/null +++ b/x/authz/types/authz.pb.go @@ -0,0 +1,759 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/authz/v1beta1/authz.proto + +package types + +import ( + fmt "fmt" + types1 "github.com/cosmos/cosmos-sdk/codec/types" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" + _ "github.com/golang/protobuf/ptypes/timestamp" + _ "github.com/regen-network/cosmos-proto" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// SendAuthorization allows the grantee to spend up to spend_limit coins from +// the granter's account. +type SendAuthorization struct { + SpendLimit github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,1,rep,name=spend_limit,json=spendLimit,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"spend_limit"` +} + +func (m *SendAuthorization) Reset() { *m = SendAuthorization{} } +func (m *SendAuthorization) String() string { return proto.CompactTextString(m) } +func (*SendAuthorization) ProtoMessage() {} +func (*SendAuthorization) Descriptor() ([]byte, []int) { + return fileDescriptor_544dc2e84b61c637, []int{0} +} +func (m *SendAuthorization) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SendAuthorization) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SendAuthorization.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 *SendAuthorization) XXX_Merge(src proto.Message) { + xxx_messageInfo_SendAuthorization.Merge(m, src) +} +func (m *SendAuthorization) XXX_Size() int { + return m.Size() +} +func (m *SendAuthorization) XXX_DiscardUnknown() { + xxx_messageInfo_SendAuthorization.DiscardUnknown(m) +} + +var xxx_messageInfo_SendAuthorization proto.InternalMessageInfo + +func (m *SendAuthorization) GetSpendLimit() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.SpendLimit + } + return nil +} + +// GenericAuthorization gives the grantee unrestricted permissions to execute +// the provided method on behalf of the granter's account. +type GenericAuthorization struct { + // method name to grant unrestricted permissions to execute + // Note: MethodName() is already a method on `GenericAuthorization` type, + // we need some custom naming here so using `MessageName` + MessageName string `protobuf:"bytes,1,opt,name=method_name,json=methodName,proto3" json:"method_name,omitempty"` +} + +func (m *GenericAuthorization) Reset() { *m = GenericAuthorization{} } +func (m *GenericAuthorization) String() string { return proto.CompactTextString(m) } +func (*GenericAuthorization) ProtoMessage() {} +func (*GenericAuthorization) Descriptor() ([]byte, []int) { + return fileDescriptor_544dc2e84b61c637, []int{1} +} +func (m *GenericAuthorization) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenericAuthorization) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenericAuthorization.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 *GenericAuthorization) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenericAuthorization.Merge(m, src) +} +func (m *GenericAuthorization) XXX_Size() int { + return m.Size() +} +func (m *GenericAuthorization) XXX_DiscardUnknown() { + xxx_messageInfo_GenericAuthorization.DiscardUnknown(m) +} + +var xxx_messageInfo_GenericAuthorization proto.InternalMessageInfo + +func (m *GenericAuthorization) GetMessageName() string { + if m != nil { + return m.MessageName + } + return "" +} + +// AuthorizationGrant gives permissions to execute +// the provide method with expiration time. +type AuthorizationGrant struct { + Authorization *types1.Any `protobuf:"bytes,1,opt,name=authorization,proto3" json:"authorization,omitempty"` + Expiration time.Time `protobuf:"bytes,2,opt,name=expiration,proto3,stdtime" json:"expiration"` +} + +func (m *AuthorizationGrant) Reset() { *m = AuthorizationGrant{} } +func (m *AuthorizationGrant) String() string { return proto.CompactTextString(m) } +func (*AuthorizationGrant) ProtoMessage() {} +func (*AuthorizationGrant) Descriptor() ([]byte, []int) { + return fileDescriptor_544dc2e84b61c637, []int{2} +} +func (m *AuthorizationGrant) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AuthorizationGrant) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AuthorizationGrant.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 *AuthorizationGrant) XXX_Merge(src proto.Message) { + xxx_messageInfo_AuthorizationGrant.Merge(m, src) +} +func (m *AuthorizationGrant) XXX_Size() int { + return m.Size() +} +func (m *AuthorizationGrant) XXX_DiscardUnknown() { + xxx_messageInfo_AuthorizationGrant.DiscardUnknown(m) +} + +var xxx_messageInfo_AuthorizationGrant proto.InternalMessageInfo + +func (m *AuthorizationGrant) GetAuthorization() *types1.Any { + if m != nil { + return m.Authorization + } + return nil +} + +func (m *AuthorizationGrant) GetExpiration() time.Time { + if m != nil { + return m.Expiration + } + return time.Time{} +} + +func init() { + proto.RegisterType((*SendAuthorization)(nil), "cosmos.authz.v1beta1.SendAuthorization") + proto.RegisterType((*GenericAuthorization)(nil), "cosmos.authz.v1beta1.GenericAuthorization") + proto.RegisterType((*AuthorizationGrant)(nil), "cosmos.authz.v1beta1.AuthorizationGrant") +} + +func init() { proto.RegisterFile("cosmos/authz/v1beta1/authz.proto", fileDescriptor_544dc2e84b61c637) } + +var fileDescriptor_544dc2e84b61c637 = []byte{ + // 410 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0xbf, 0x8e, 0xd3, 0x30, + 0x1c, 0xc7, 0x63, 0x90, 0x10, 0x38, 0x3a, 0xa1, 0x46, 0x19, 0xee, 0x3a, 0x24, 0xd5, 0x4d, 0x15, + 0xd2, 0x39, 0x77, 0xc7, 0xc6, 0x76, 0xe1, 0xa4, 0x5b, 0x38, 0x86, 0xc0, 0x04, 0x43, 0xe5, 0x24, + 0x26, 0xb1, 0xa8, 0xed, 0x28, 0x76, 0xd0, 0xf5, 0x9e, 0xa2, 0x03, 0x2f, 0x01, 0x33, 0x0f, 0x51, + 0x31, 0x55, 0x4c, 0x4c, 0x2d, 0x4a, 0x5f, 0x04, 0xc5, 0x76, 0x50, 0x53, 0x10, 0x53, 0xfc, 0xfb, + 0xf3, 0xfd, 0xe4, 0x9b, 0x6f, 0x0c, 0x27, 0x99, 0x90, 0x4c, 0xc8, 0x08, 0x37, 0xaa, 0xbc, 0x8f, + 0x3e, 0x5d, 0xa4, 0x44, 0xe1, 0x0b, 0x53, 0xa1, 0xaa, 0x16, 0x4a, 0x78, 0xbe, 0xd9, 0x40, 0xa6, + 0x67, 0x37, 0xc6, 0x81, 0xd5, 0xa5, 0x58, 0x92, 0x3f, 0xb2, 0x4c, 0x50, 0x6e, 0x54, 0xe3, 0x13, + 0x33, 0x9f, 0xe9, 0x2a, 0xb2, 0x08, 0x33, 0x0a, 0x0b, 0x21, 0x8a, 0x39, 0x89, 0x74, 0x95, 0x36, + 0x1f, 0x22, 0x45, 0x19, 0x91, 0x0a, 0xb3, 0xca, 0x2e, 0xf8, 0x85, 0x28, 0x84, 0x11, 0x76, 0xa7, + 0x9e, 0x78, 0x28, 0xc3, 0x7c, 0x61, 0x46, 0xa7, 0x9f, 0x01, 0x1c, 0xbd, 0x21, 0x3c, 0xbf, 0x6a, + 0x54, 0x29, 0x6a, 0x7a, 0x8f, 0x15, 0x15, 0xdc, 0x9b, 0x43, 0x57, 0x56, 0x84, 0xe7, 0xb3, 0x39, + 0x65, 0x54, 0x1d, 0x83, 0xc9, 0xc3, 0xa9, 0x7b, 0x79, 0x82, 0xac, 0x97, 0xce, 0x78, 0xff, 0x35, + 0xe8, 0xa5, 0xa0, 0x3c, 0x3e, 0x5f, 0x6d, 0x42, 0xe7, 0xeb, 0x36, 0x9c, 0x16, 0x54, 0x95, 0x4d, + 0x8a, 0x32, 0xc1, 0xac, 0x71, 0xfb, 0x38, 0x93, 0xf9, 0xc7, 0x48, 0x2d, 0x2a, 0x22, 0xb5, 0x40, + 0x26, 0x50, 0xf3, 0x5f, 0x75, 0xf8, 0x17, 0xa3, 0x1f, 0xdf, 0xce, 0x8e, 0x06, 0x06, 0x4e, 0xdf, + 0x43, 0xff, 0x86, 0x70, 0x52, 0xd3, 0x6c, 0x68, 0xec, 0x1c, 0xba, 0x8c, 0xa8, 0x52, 0xe4, 0x33, + 0x8e, 0x19, 0x39, 0x06, 0x13, 0x30, 0x7d, 0x12, 0x3f, 0x6d, 0x37, 0xa1, 0x7b, 0x4b, 0xa4, 0xc4, + 0x05, 0x79, 0x8d, 0x19, 0x49, 0xa0, 0xd9, 0xe9, 0xce, 0xff, 0x82, 0x7f, 0x01, 0xd0, 0x1b, 0x74, + 0x6e, 0x6a, 0xcc, 0x95, 0x77, 0x0b, 0x8f, 0xf0, 0x7e, 0x57, 0xd3, 0xdd, 0x4b, 0x1f, 0x99, 0xf4, + 0x50, 0x9f, 0x1e, 0xba, 0xe2, 0x8b, 0x78, 0xf4, 0xfd, 0x10, 0x9b, 0x0c, 0xd5, 0xde, 0x35, 0x84, + 0xe4, 0xae, 0xa2, 0xb5, 0x61, 0x3d, 0xd0, 0xac, 0xf1, 0x5f, 0xac, 0xb7, 0xfd, 0x0f, 0x8c, 0x1f, + 0x77, 0x19, 0x2e, 0xb7, 0x21, 0x48, 0xf6, 0x74, 0xf1, 0xf5, 0xaa, 0x0d, 0xc0, 0xba, 0x0d, 0xc0, + 0xaf, 0x36, 0x00, 0xcb, 0x5d, 0xe0, 0xac, 0x77, 0x81, 0xf3, 0x73, 0x17, 0x38, 0xef, 0x9e, 0xfd, + 0x37, 0xeb, 0x3b, 0x7b, 0x2d, 0x75, 0xe6, 0xe9, 0x23, 0xfd, 0xbe, 0xe7, 0xbf, 0x03, 0x00, 0x00, + 0xff, 0xff, 0x87, 0x61, 0xb9, 0xa8, 0xb3, 0x02, 0x00, 0x00, +} + +func (m *SendAuthorization) 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 *SendAuthorization) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SendAuthorization) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.SpendLimit) > 0 { + for iNdEx := len(m.SpendLimit) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.SpendLimit[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuthz(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *GenericAuthorization) 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 *GenericAuthorization) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenericAuthorization) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.MessageName) > 0 { + i -= len(m.MessageName) + copy(dAtA[i:], m.MessageName) + i = encodeVarintAuthz(dAtA, i, uint64(len(m.MessageName))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *AuthorizationGrant) 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 *AuthorizationGrant) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AuthorizationGrant) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n1, err1 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Expiration, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Expiration):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintAuthz(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x12 + if m.Authorization != nil { + { + size, err := m.Authorization.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuthz(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintAuthz(dAtA []byte, offset int, v uint64) int { + offset -= sovAuthz(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *SendAuthorization) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.SpendLimit) > 0 { + for _, e := range m.SpendLimit { + l = e.Size() + n += 1 + l + sovAuthz(uint64(l)) + } + } + return n +} + +func (m *GenericAuthorization) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.MessageName) + if l > 0 { + n += 1 + l + sovAuthz(uint64(l)) + } + return n +} + +func (m *AuthorizationGrant) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Authorization != nil { + l = m.Authorization.Size() + n += 1 + l + sovAuthz(uint64(l)) + } + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Expiration) + n += 1 + l + sovAuthz(uint64(l)) + return n +} + +func sovAuthz(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozAuthz(x uint64) (n int) { + return sovAuthz(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *SendAuthorization) 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 ErrIntOverflowAuthz + } + 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: SendAuthorization: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SendAuthorization: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SpendLimit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuthz + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuthz + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SpendLimit = append(m.SpendLimit, types.Coin{}) + if err := m.SpendLimit[len(m.SpendLimit)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAuthz(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuthz + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GenericAuthorization) 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 ErrIntOverflowAuthz + } + 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: GenericAuthorization: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenericAuthorization: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MessageName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthAuthz + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthAuthz + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MessageName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAuthz(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuthz + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AuthorizationGrant) 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 ErrIntOverflowAuthz + } + 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: AuthorizationGrant: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AuthorizationGrant: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authorization", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuthz + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuthz + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Authorization == nil { + m.Authorization = &types1.Any{} + } + if err := m.Authorization.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiration", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuthz + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuthz + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Expiration, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAuthz(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuthz + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipAuthz(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAuthz + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAuthz + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAuthz + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthAuthz + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupAuthz + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthAuthz + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthAuthz = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowAuthz = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupAuthz = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/authz/types/codec.go b/x/authz/types/codec.go new file mode 100644 index 000000000000..88b30932df9f --- /dev/null +++ b/x/authz/types/codec.go @@ -0,0 +1,25 @@ +package types + +import ( + types "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" +) + +// RegisterInterfaces registers the interfaces types with the interface registry +func RegisterInterfaces(registry types.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.MsgRequest)(nil), + &MsgGrantAuthorizationRequest{}, + &MsgRevokeAuthorizationRequest{}, + &MsgExecAuthorizedRequest{}, + ) + + registry.RegisterInterface( + "cosmos.authz.v1beta1.Authorization", + (*Authorization)(nil), + &SendAuthorization{}, + &GenericAuthorization{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} diff --git a/x/authz/types/errors.go b/x/authz/types/errors.go new file mode 100644 index 000000000000..dc4357b1f9a2 --- /dev/null +++ b/x/authz/types/errors.go @@ -0,0 +1,10 @@ +package types + +import ( + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// x/authz module sentinel errors +var ( + ErrInvalidExpirationTime = sdkerrors.Register(ModuleName, 3, "expiration time of authorization should be more than current time") +) diff --git a/x/authz/types/events.go b/x/authz/types/events.go new file mode 100644 index 000000000000..9da0f68b14fd --- /dev/null +++ b/x/authz/types/events.go @@ -0,0 +1,14 @@ +package types + +// authz module events +const ( + EventGrantAuthorization = "grant-authorization" + EventRevokeAuthorization = "revoke-authorization" + EventExecuteAuthorization = "execute-authorization" + + AttributeKeyGrantType = "grant-type" + AttributeKeyGranteeAddress = "grantee" + AttributeKeyGranterAddress = "granter" + + AttributeValueCategory = ModuleName +) diff --git a/x/authz/types/expected_keepers.go b/x/authz/types/expected_keepers.go new file mode 100644 index 000000000000..ef7869dd2c7d --- /dev/null +++ b/x/authz/types/expected_keepers.go @@ -0,0 +1,16 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +// AccountKeeper defines the expected account keeper (noalias) +type AccountKeeper interface { + GetAccount(ctx sdk.Context, addr sdk.AccAddress) types.AccountI +} + +// BankKeeper defines the expected interface needed to retrieve account balances. +type BankKeeper interface { + SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins +} diff --git a/x/authz/types/generic_authorization.go b/x/authz/types/generic_authorization.go new file mode 100644 index 000000000000..242608c6311a --- /dev/null +++ b/x/authz/types/generic_authorization.go @@ -0,0 +1,28 @@ +package types + +import ( + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var ( + _ Authorization = &GenericAuthorization{} +) + +// NewGenericAuthorization creates a new GenericAuthorization object. +func NewGenericAuthorization(methodName string) *GenericAuthorization { + return &GenericAuthorization{ + MessageName: methodName, + } +} + +// MethodName implements Authorization.MethodName. +func (cap GenericAuthorization) MethodName() string { + return cap.MessageName +} + +// Accept implements Authorization.Accept. +func (cap GenericAuthorization) Accept(msg sdk.ServiceMsg, block tmproto.Header) (allow bool, updated Authorization, delete bool) { + return true, &cap, false +} diff --git a/x/authz/types/genesis.go b/x/authz/types/genesis.go new file mode 100644 index 000000000000..6ae3529d2ec0 --- /dev/null +++ b/x/authz/types/genesis.go @@ -0,0 +1,41 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec/types" +) + +// NewGenesisState creates new GenesisState object +func NewGenesisState(entries []GrantAuthorization) *GenesisState { + return &GenesisState{ + Authorization: entries, + } +} + +// ValidateGenesis check the given genesis state has no integrity issues +func ValidateGenesis(data GenesisState) error { + return nil +} + +// DefaultGenesisState - Return a default genesis state +func DefaultGenesisState() *GenesisState { + return &GenesisState{} +} + +var _ types.UnpackInterfacesMessage = GenesisState{} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (data GenesisState) UnpackInterfaces(unpacker types.AnyUnpacker) error { + for _, authorization := range data.Authorization { + err := authorization.UnpackInterfaces(unpacker) + if err != nil { + return err + } + } + return nil +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (msg GrantAuthorization) UnpackInterfaces(unpacker types.AnyUnpacker) error { + var authorization Authorization + return unpacker.UnpackAny(msg.Authorization, &authorization) +} diff --git a/x/authz/types/genesis.pb.go b/x/authz/types/genesis.pb.go new file mode 100644 index 000000000000..0cf5c8557754 --- /dev/null +++ b/x/authz/types/genesis.pb.go @@ -0,0 +1,680 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/authz/v1beta1/genesis.proto + +package types + +import ( + fmt "fmt" + types "github.com/cosmos/cosmos-sdk/codec/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" + _ "github.com/golang/protobuf/ptypes/timestamp" + _ "github.com/regen-network/cosmos-proto" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GenesisState defines the authz module's genesis state. +type GenesisState struct { + Authorization []GrantAuthorization `protobuf:"bytes,1,rep,name=authorization,proto3" json:"authorization"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_4c2fbb971da7c892, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.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 *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetAuthorization() []GrantAuthorization { + if m != nil { + return m.Authorization + } + return nil +} + +// GrantAuthorization defines the GenesisState/GrantAuthorization type. +type GrantAuthorization struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` + Authorization *types.Any `protobuf:"bytes,3,opt,name=authorization,proto3" json:"authorization,omitempty"` + Expiration time.Time `protobuf:"bytes,4,opt,name=expiration,proto3,stdtime" json:"expiration"` +} + +func (m *GrantAuthorization) Reset() { *m = GrantAuthorization{} } +func (m *GrantAuthorization) String() string { return proto.CompactTextString(m) } +func (*GrantAuthorization) ProtoMessage() {} +func (*GrantAuthorization) Descriptor() ([]byte, []int) { + return fileDescriptor_4c2fbb971da7c892, []int{1} +} +func (m *GrantAuthorization) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GrantAuthorization) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GrantAuthorization.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 *GrantAuthorization) XXX_Merge(src proto.Message) { + xxx_messageInfo_GrantAuthorization.Merge(m, src) +} +func (m *GrantAuthorization) XXX_Size() int { + return m.Size() +} +func (m *GrantAuthorization) XXX_DiscardUnknown() { + xxx_messageInfo_GrantAuthorization.DiscardUnknown(m) +} + +var xxx_messageInfo_GrantAuthorization proto.InternalMessageInfo + +func (m *GrantAuthorization) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *GrantAuthorization) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *GrantAuthorization) GetAuthorization() *types.Any { + if m != nil { + return m.Authorization + } + return nil +} + +func (m *GrantAuthorization) GetExpiration() time.Time { + if m != nil { + return m.Expiration + } + return time.Time{} +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "cosmos.authz.v1beta1.GenesisState") + proto.RegisterType((*GrantAuthorization)(nil), "cosmos.authz.v1beta1.GrantAuthorization") +} + +func init() { + proto.RegisterFile("cosmos/authz/v1beta1/genesis.proto", fileDescriptor_4c2fbb971da7c892) +} + +var fileDescriptor_4c2fbb971da7c892 = []byte{ + // 346 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0xbb, 0x6e, 0xc2, 0x30, + 0x14, 0x86, 0xe3, 0x82, 0x7a, 0x31, 0x65, 0x68, 0xc4, 0x90, 0x22, 0x35, 0x20, 0xa6, 0xa8, 0x12, + 0xb6, 0xa0, 0x4f, 0x40, 0x84, 0xc4, 0xd4, 0x85, 0x32, 0x75, 0xa9, 0x1c, 0x70, 0x4d, 0xd4, 0x26, + 0x8e, 0xe2, 0x43, 0x05, 0x3c, 0x05, 0x0f, 0xd3, 0x87, 0x40, 0x9d, 0x18, 0xbb, 0xf4, 0x22, 0x78, + 0x91, 0x2a, 0x71, 0xa2, 0x72, 0x9b, 0xe2, 0xf8, 0xff, 0xce, 0xf9, 0x7f, 0x9f, 0x83, 0x1b, 0x43, + 0xa9, 0x02, 0xa9, 0x28, 0x9b, 0xc0, 0x78, 0x4e, 0xdf, 0x5a, 0x1e, 0x07, 0xd6, 0xa2, 0x82, 0x87, + 0x5c, 0xf9, 0x8a, 0x44, 0xb1, 0x04, 0x69, 0x56, 0x34, 0x43, 0x52, 0x86, 0x64, 0x4c, 0xb5, 0x26, + 0xa4, 0x14, 0xaf, 0x9c, 0xa6, 0x8c, 0x37, 0x79, 0xa6, 0xe0, 0x07, 0x5c, 0x01, 0x0b, 0x22, 0x5d, + 0x56, 0xbd, 0xde, 0x07, 0x58, 0x38, 0xcb, 0xa4, 0x8a, 0x90, 0x42, 0xa6, 0x47, 0x9a, 0x9c, 0xf2, + 0x02, 0xed, 0xf3, 0xa4, 0x85, 0xcc, 0x54, 0x4b, 0x37, 0x47, 0x63, 0xc2, 0x54, 0xcb, 0x8d, 0x11, + 0xbe, 0xec, 0xe9, 0xc8, 0x0f, 0xc0, 0x80, 0x9b, 0x03, 0x5c, 0x4e, 0x48, 0x19, 0xfb, 0x73, 0x06, + 0xbe, 0x0c, 0x2d, 0x54, 0x2f, 0x38, 0xa5, 0xb6, 0x43, 0x8e, 0xbd, 0x84, 0xf4, 0x62, 0x16, 0x42, + 0x67, 0x9b, 0x77, 0x8b, 0xcb, 0xef, 0x9a, 0xd1, 0xdf, 0x6d, 0xd2, 0xf8, 0x42, 0xd8, 0x3c, 0x64, + 0x4d, 0x0b, 0x9f, 0x89, 0xe4, 0x96, 0xc7, 0x16, 0xaa, 0x23, 0xe7, 0xa2, 0x9f, 0xff, 0xfe, 0x2b, + 0xdc, 0x3a, 0xd9, 0x56, 0xb8, 0x79, 0xbf, 0x1f, 0xb0, 0x50, 0x47, 0x4e, 0xa9, 0x5d, 0x21, 0x7a, + 0x66, 0x24, 0x9f, 0x19, 0xe9, 0x84, 0x33, 0xf7, 0xea, 0xe3, 0xbd, 0x59, 0xde, 0xf1, 0xdc, 0x4b, + 0x66, 0x76, 0x31, 0xe6, 0xd3, 0xc8, 0x8f, 0x75, 0xaf, 0x62, 0xda, 0xab, 0x7a, 0xd0, 0x6b, 0x90, + 0x2f, 0xc8, 0x3d, 0x4f, 0x9e, 0xb7, 0xf8, 0xa9, 0xa1, 0xfe, 0x56, 0x9d, 0xdb, 0x5d, 0xae, 0x6d, + 0xb4, 0x5a, 0xdb, 0xe8, 0x77, 0x6d, 0xa3, 0xc5, 0xc6, 0x36, 0x56, 0x1b, 0xdb, 0xf8, 0xdc, 0xd8, + 0xc6, 0xe3, 0xad, 0xf0, 0x61, 0x3c, 0xf1, 0xc8, 0x50, 0x06, 0xd9, 0x5e, 0xb2, 0x4f, 0x53, 0x8d, + 0x5e, 0xe8, 0x34, 0x5b, 0x0b, 0xcc, 0x22, 0xae, 0xbc, 0xd3, 0xd4, 0xef, 0xee, 0x2f, 0x00, 0x00, + 0xff, 0xff, 0x52, 0x9c, 0x43, 0x7a, 0x5a, 0x02, 0x00, 0x00, +} + +func (m *GenesisState) 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 *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Authorization) > 0 { + for iNdEx := len(m.Authorization) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Authorization[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *GrantAuthorization) 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 *GrantAuthorization) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GrantAuthorization) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n1, err1 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Expiration, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Expiration):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintGenesis(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x22 + if m.Authorization != nil { + { + size, err := m.Authorization.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Granter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Authorization) > 0 { + for _, e := range m.Authorization { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func (m *GrantAuthorization) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + if m.Authorization != nil { + l = m.Authorization.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Expiration) + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) 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 ErrIntOverflowGenesis + } + 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: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authorization", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authorization = append(m.Authorization, GrantAuthorization{}) + if err := m.Authorization[len(m.Authorization)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GrantAuthorization) 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 ErrIntOverflowGenesis + } + 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: GrantAuthorization: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GrantAuthorization: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authorization", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Authorization == nil { + m.Authorization = &types.Any{} + } + if err := m.Authorization.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiration", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Expiration, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/authz/types/keys.go b/x/authz/types/keys.go new file mode 100644 index 000000000000..3be659c5aeb8 --- /dev/null +++ b/x/authz/types/keys.go @@ -0,0 +1,41 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + // ModuleName is the module name constant used in many places + ModuleName = "authz" + + // StoreKey is the store key string for authz + StoreKey = ModuleName + + // RouterKey is the message route for authz + RouterKey = ModuleName + + // QuerierRoute is the querier route for authz + QuerierRoute = ModuleName +) + +// Keys for authz store +// Items are stored with the following key: values +// +// - 0x01: Grant + +var ( + // Keys for store prefixes + GrantKey = []byte{0x01} // prefix for each key +) + +// GetAuthorizationStoreKey - return authorization store key +func GetAuthorizationStoreKey(grantee sdk.AccAddress, granter sdk.AccAddress, msgType string) []byte { + return append(append(append(GrantKey, granter.Bytes()...), grantee.Bytes()...), []byte(msgType)...) +} + +// ExtractAddressesFromGrantKey - split granter & grantee address from the authorization key +func ExtractAddressesFromGrantKey(key []byte) (granterAddr, granteeAddr sdk.AccAddress) { + granterAddr = sdk.AccAddress(key[1 : sdk.AddrLen+1]) + granteeAddr = sdk.AccAddress(key[sdk.AddrLen+1 : sdk.AddrLen*2+1]) + return granterAddr, granteeAddr +} diff --git a/x/authz/types/keys_test.go b/x/authz/types/keys_test.go new file mode 100644 index 000000000000..1d6d7cef6623 --- /dev/null +++ b/x/authz/types/keys_test.go @@ -0,0 +1,20 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var granter = sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) +var grantee = sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) +var msgType = SendAuthorization{}.MethodName() + +func TestGrantkey(t *testing.T) { + granter1, grantee1 := ExtractAddressesFromGrantKey(GetAuthorizationStoreKey(grantee, granter, msgType)) + require.Equal(t, granter, granter1) + require.Equal(t, grantee, grantee1) +} diff --git a/x/authz/types/msgs.go b/x/authz/types/msgs.go new file mode 100644 index 000000000000..59ae59c20aa6 --- /dev/null +++ b/x/authz/types/msgs.go @@ -0,0 +1,215 @@ +package types + +import ( + "time" + + "github.com/gogo/protobuf/proto" + + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +var ( + _ sdk.MsgRequest = &MsgGrantAuthorizationRequest{} + _ sdk.MsgRequest = &MsgRevokeAuthorizationRequest{} + _ sdk.MsgRequest = &MsgExecAuthorizedRequest{} + + _ types.UnpackInterfacesMessage = &MsgGrantAuthorizationRequest{} + _ types.UnpackInterfacesMessage = &MsgExecAuthorizedRequest{} +) + +// NewMsgGrantAuthorization creates a new MsgGrantAuthorization +//nolint:interfacer +func NewMsgGrantAuthorization(granter sdk.AccAddress, grantee sdk.AccAddress, authorization Authorization, expiration time.Time) (*MsgGrantAuthorizationRequest, error) { + m := &MsgGrantAuthorizationRequest{ + Granter: granter.String(), + Grantee: grantee.String(), + Expiration: expiration, + } + err := m.SetAuthorization(authorization) + if err != nil { + return nil, err + } + return m, nil +} + +// GetSigners implements Msg +func (msg MsgGrantAuthorizationRequest) GetSigners() []sdk.AccAddress { + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + panic(err) + } + return []sdk.AccAddress{granter} +} + +// ValidateBasic implements Msg +func (msg MsgGrantAuthorizationRequest) ValidateBasic() error { + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid granter address") + } + grantee, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid granter address") + } + + if granter.Equals(grantee) { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "granter and grantee cannot be same") + } + + if msg.Expiration.Unix() < time.Now().Unix() { + return sdkerrors.Wrap(ErrInvalidExpirationTime, "Time can't be in the past") + } + + return nil +} + +// GetGrantAuthorization returns the cache value from the MsgGrantAuthorization.Authorization if present. +func (msg *MsgGrantAuthorizationRequest) GetGrantAuthorization() Authorization { + authorization, ok := msg.Authorization.GetCachedValue().(Authorization) + if !ok { + return nil + } + return authorization +} + +// SetAuthorization converts Authorization to any and adds it to MsgGrantAuthorization.Authorization. +func (msg *MsgGrantAuthorizationRequest) SetAuthorization(authorization Authorization) error { + m, ok := authorization.(proto.Message) + if !ok { + return sdkerrors.Wrapf(sdkerrors.ErrPackAny, "can't proto marshal %T", m) + } + any, err := types.NewAnyWithValue(m) + if err != nil { + return err + } + msg.Authorization = any + return nil +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (msg MsgExecAuthorizedRequest) UnpackInterfaces(unpacker types.AnyUnpacker) error { + for _, x := range msg.Msgs { + var msgExecAuthorized sdk.MsgRequest + err := unpacker.UnpackAny(x, &msgExecAuthorized) + if err != nil { + return err + } + } + + return nil +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (msg MsgGrantAuthorizationRequest) UnpackInterfaces(unpacker types.AnyUnpacker) error { + var authorization Authorization + return unpacker.UnpackAny(msg.Authorization, &authorization) +} + +// NewMsgRevokeAuthorization creates a new MsgRevokeAuthorization +//nolint:interfacer +func NewMsgRevokeAuthorization(granter sdk.AccAddress, grantee sdk.AccAddress, methodName string) MsgRevokeAuthorizationRequest { + return MsgRevokeAuthorizationRequest{ + Granter: granter.String(), + Grantee: grantee.String(), + MethodName: methodName, + } +} + +// GetSigners implements Msg +func (msg MsgRevokeAuthorizationRequest) GetSigners() []sdk.AccAddress { + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + panic(err) + } + return []sdk.AccAddress{granter} +} + +// ValidateBasic implements MsgRequest.ValidateBasic +func (msg MsgRevokeAuthorizationRequest) ValidateBasic() error { + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid granter address") + } + grantee, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid grantee address") + } + + if granter.Equals(grantee) { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "granter and grantee cannot be same") + } + + if msg.MethodName == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "missing method name") + } + + return nil +} + +// NewMsgExecAuthorized creates a new MsgExecAuthorized +//nolint:interfacer +func NewMsgExecAuthorized(grantee sdk.AccAddress, msgs []sdk.ServiceMsg) MsgExecAuthorizedRequest { + msgsAny := make([]*types.Any, len(msgs)) + for i, msg := range msgs { + bz, err := proto.Marshal(msg.Request) + if err != nil { + panic(err) + } + + anyMsg := &types.Any{ + TypeUrl: msg.MethodName, + Value: bz, + } + + msgsAny[i] = anyMsg + } + + return MsgExecAuthorizedRequest{ + Grantee: grantee.String(), + Msgs: msgsAny, + } +} + +// GetServiceMsgs returns the cache values from the MsgExecAuthorized.Msgs if present. +func (msg MsgExecAuthorizedRequest) GetServiceMsgs() ([]sdk.ServiceMsg, error) { + msgs := make([]sdk.ServiceMsg, len(msg.Msgs)) + for i, msgAny := range msg.Msgs { + msgReq, ok := msgAny.GetCachedValue().(sdk.MsgRequest) + if !ok { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "messages contains %T which is not a sdk.MsgRequest", msgAny) + } + srvMsg := sdk.ServiceMsg{ + MethodName: msgAny.TypeUrl, + Request: msgReq, + } + + msgs[i] = srvMsg + } + + return msgs, nil +} + +// GetSigners implements Msg +func (msg MsgExecAuthorizedRequest) GetSigners() []sdk.AccAddress { + grantee, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + panic(err) + } + return []sdk.AccAddress{grantee} +} + +// ValidateBasic implements Msg +func (msg MsgExecAuthorizedRequest) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid grantee address") + } + + if len(msg.Msgs) == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "messages cannot be empty") + } + + return nil +} diff --git a/x/authz/types/msgs_test.go b/x/authz/types/msgs_test.go new file mode 100644 index 000000000000..3c6cea890576 --- /dev/null +++ b/x/authz/types/msgs_test.go @@ -0,0 +1,103 @@ +package types_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +var ( + coinsPos = sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) + granter = sdk.AccAddress("_______granter______") + grantee = sdk.AccAddress("_______grantee______") +) + +func TestMsgExecAuthorized(t *testing.T) { + tests := []struct { + title string + grantee sdk.AccAddress + msgs []sdk.ServiceMsg + expectPass bool + }{ + {"nil grantee address", nil, []sdk.ServiceMsg{}, false}, + {"zero-messages test: should fail", grantee, []sdk.ServiceMsg{}, false}, + {"valid test: msg type", grantee, []sdk.ServiceMsg{ + { + MethodName: types.SendAuthorization{}.MethodName(), + Request: &banktypes.MsgSend{ + Amount: sdk.NewCoins(sdk.NewInt64Coin("steak", 2)), + FromAddress: granter.String(), + ToAddress: grantee.String(), + }, + }, + }, true}, + } + for i, tc := range tests { + msg := types.NewMsgExecAuthorized(tc.grantee, tc.msgs) + if tc.expectPass { + require.NoError(t, msg.ValidateBasic(), "test: %v", i) + } else { + require.Error(t, msg.ValidateBasic(), "test: %v", i) + } + } +} +func TestMsgRevokeAuthorization(t *testing.T) { + tests := []struct { + title string + granter, grantee sdk.AccAddress + msgType string + expectPass bool + }{ + {"nil Granter address", nil, grantee, "hello", false}, + {"nil Grantee address", granter, nil, "hello", false}, + {"nil Granter and Grantee address", nil, nil, "hello", false}, + {"valid test case", granter, grantee, "hello", true}, + } + for i, tc := range tests { + msg := types.NewMsgRevokeAuthorization(tc.granter, tc.grantee, tc.msgType) + if tc.expectPass { + require.NoError(t, msg.ValidateBasic(), "test: %v", i) + } else { + require.Error(t, msg.ValidateBasic(), "test: %v", i) + } + } +} + +func TestMsgGrantAuthorization(t *testing.T) { + tests := []struct { + title string + granter, grantee sdk.AccAddress + authorization types.Authorization + expiration time.Time + expectErr bool + expectPass bool + }{ + {"nil granter address", nil, grantee, &types.SendAuthorization{SpendLimit: coinsPos}, time.Now(), false, false}, + {"nil grantee address", granter, nil, &types.SendAuthorization{SpendLimit: coinsPos}, time.Now(), false, false}, + {"nil granter and grantee address", nil, nil, &types.SendAuthorization{SpendLimit: coinsPos}, time.Now(), false, false}, + {"nil authorization", granter, grantee, nil, time.Now(), true, false}, + {"valid test case", granter, grantee, &types.SendAuthorization{SpendLimit: coinsPos}, time.Now().AddDate(0, 1, 0), false, true}, + {"past time", granter, grantee, &types.SendAuthorization{SpendLimit: coinsPos}, time.Now().AddDate(0, 0, -1), false, false}, + } + for i, tc := range tests { + msg, err := types.NewMsgGrantAuthorization( + tc.granter, tc.grantee, tc.authorization, tc.expiration, + ) + if !tc.expectErr { + require.NoError(t, err) + } else { + continue + } + if tc.expectPass { + require.NoError(t, msg.ValidateBasic(), "test: %v", i) + } else { + require.Error(t, msg.ValidateBasic(), "test: %v", i) + } + } +} diff --git a/x/authz/types/query.pb.go b/x/authz/types/query.pb.go new file mode 100644 index 000000000000..91accaa109d5 --- /dev/null +++ b/x/authz/types/query.pb.go @@ -0,0 +1,1278 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/authz/v1beta1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-sdk/codec/types" + query "github.com/cosmos/cosmos-sdk/types/query" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + _ "github.com/regen-network/cosmos-proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// QueryAuthorizationRequest is the request type for the Query/Authorization RPC method. +type QueryAuthorizationRequest struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` + MethodName string `protobuf:"bytes,3,opt,name=method_name,json=methodName,proto3" json:"method_name,omitempty"` +} + +func (m *QueryAuthorizationRequest) Reset() { *m = QueryAuthorizationRequest{} } +func (m *QueryAuthorizationRequest) String() string { return proto.CompactTextString(m) } +func (*QueryAuthorizationRequest) ProtoMessage() {} +func (*QueryAuthorizationRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_376d714ffdeb1545, []int{0} +} +func (m *QueryAuthorizationRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAuthorizationRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAuthorizationRequest.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 *QueryAuthorizationRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAuthorizationRequest.Merge(m, src) +} +func (m *QueryAuthorizationRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryAuthorizationRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAuthorizationRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAuthorizationRequest proto.InternalMessageInfo + +func (m *QueryAuthorizationRequest) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *QueryAuthorizationRequest) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *QueryAuthorizationRequest) GetMethodName() string { + if m != nil { + return m.MethodName + } + return "" +} + +// QueryAuthorizationResponse is the response type for the Query/Authorization RPC method. +type QueryAuthorizationResponse struct { + // authorization is a authorization granted for grantee by granter. + Authorization *AuthorizationGrant `protobuf:"bytes,1,opt,name=authorization,proto3" json:"authorization,omitempty"` +} + +func (m *QueryAuthorizationResponse) Reset() { *m = QueryAuthorizationResponse{} } +func (m *QueryAuthorizationResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAuthorizationResponse) ProtoMessage() {} +func (*QueryAuthorizationResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_376d714ffdeb1545, []int{1} +} +func (m *QueryAuthorizationResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAuthorizationResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAuthorizationResponse.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 *QueryAuthorizationResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAuthorizationResponse.Merge(m, src) +} +func (m *QueryAuthorizationResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAuthorizationResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAuthorizationResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAuthorizationResponse proto.InternalMessageInfo + +func (m *QueryAuthorizationResponse) GetAuthorization() *AuthorizationGrant { + if m != nil { + return m.Authorization + } + return nil +} + +// QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. +type QueryAuthorizationsRequest struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` + // pagination defines an pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,3,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryAuthorizationsRequest) Reset() { *m = QueryAuthorizationsRequest{} } +func (m *QueryAuthorizationsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryAuthorizationsRequest) ProtoMessage() {} +func (*QueryAuthorizationsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_376d714ffdeb1545, []int{2} +} +func (m *QueryAuthorizationsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAuthorizationsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAuthorizationsRequest.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 *QueryAuthorizationsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAuthorizationsRequest.Merge(m, src) +} +func (m *QueryAuthorizationsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryAuthorizationsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAuthorizationsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAuthorizationsRequest proto.InternalMessageInfo + +func (m *QueryAuthorizationsRequest) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *QueryAuthorizationsRequest) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *QueryAuthorizationsRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. +type QueryAuthorizationsResponse struct { + // authorizations is a list of grants granted for grantee by granter. + Authorizations []*AuthorizationGrant `protobuf:"bytes,1,rep,name=authorizations,proto3" json:"authorizations,omitempty"` + // pagination defines an pagination for the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryAuthorizationsResponse) Reset() { *m = QueryAuthorizationsResponse{} } +func (m *QueryAuthorizationsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAuthorizationsResponse) ProtoMessage() {} +func (*QueryAuthorizationsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_376d714ffdeb1545, []int{3} +} +func (m *QueryAuthorizationsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAuthorizationsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAuthorizationsResponse.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 *QueryAuthorizationsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAuthorizationsResponse.Merge(m, src) +} +func (m *QueryAuthorizationsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAuthorizationsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAuthorizationsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAuthorizationsResponse proto.InternalMessageInfo + +func (m *QueryAuthorizationsResponse) GetAuthorizations() []*AuthorizationGrant { + if m != nil { + return m.Authorizations + } + return nil +} + +func (m *QueryAuthorizationsResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +func init() { + proto.RegisterType((*QueryAuthorizationRequest)(nil), "cosmos.authz.v1beta1.QueryAuthorizationRequest") + proto.RegisterType((*QueryAuthorizationResponse)(nil), "cosmos.authz.v1beta1.QueryAuthorizationResponse") + proto.RegisterType((*QueryAuthorizationsRequest)(nil), "cosmos.authz.v1beta1.QueryAuthorizationsRequest") + proto.RegisterType((*QueryAuthorizationsResponse)(nil), "cosmos.authz.v1beta1.QueryAuthorizationsResponse") +} + +func init() { proto.RegisterFile("cosmos/authz/v1beta1/query.proto", fileDescriptor_376d714ffdeb1545) } + +var fileDescriptor_376d714ffdeb1545 = []byte{ + // 489 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x94, 0xbf, 0x6f, 0xd4, 0x30, + 0x14, 0xc7, 0xcf, 0x77, 0x02, 0x84, 0x4f, 0xed, 0x60, 0x75, 0x48, 0x03, 0x0a, 0xa7, 0x0c, 0x50, + 0x55, 0x22, 0xe6, 0x8e, 0xbf, 0xa0, 0xa5, 0xa2, 0x82, 0xa1, 0x2a, 0x19, 0x59, 0x2a, 0xa7, 0x7d, + 0x38, 0x11, 0x8d, 0x9d, 0xc6, 0x0e, 0xa2, 0x45, 0x2c, 0xac, 0x2c, 0x48, 0x2c, 0xfc, 0x29, 0x2c, + 0x0c, 0x6c, 0x8c, 0x95, 0x58, 0x18, 0xd1, 0x1d, 0x7f, 0x08, 0x8a, 0xed, 0xb4, 0x09, 0x0a, 0x6a, + 0xab, 0x4e, 0xb1, 0xdf, 0xaf, 0xef, 0xe7, 0x3d, 0x3f, 0x05, 0x4f, 0xf6, 0xa5, 0xca, 0xa5, 0xa2, + 0xac, 0xd2, 0xe9, 0x09, 0x7d, 0x33, 0x4d, 0x40, 0xb3, 0x29, 0x3d, 0xaa, 0xa0, 0x3c, 0x8e, 0x8a, + 0x52, 0x6a, 0x49, 0x56, 0x6c, 0x44, 0x64, 0x22, 0x22, 0x17, 0xe1, 0xaf, 0x70, 0xc9, 0xa5, 0x09, + 0xa0, 0xf5, 0xc9, 0xc6, 0xfa, 0xab, 0x5c, 0x4a, 0x7e, 0x08, 0xd4, 0xdc, 0x92, 0xea, 0x15, 0x65, + 0xc2, 0x95, 0xf1, 0xef, 0x3a, 0x17, 0x2b, 0x32, 0xca, 0x84, 0x90, 0x9a, 0xe9, 0x4c, 0x0a, 0xd5, + 0x24, 0x5a, 0x91, 0x3d, 0x5b, 0xd1, 0x29, 0x5a, 0xd7, 0xba, 0x23, 0x4c, 0x98, 0x02, 0x0b, 0x76, + 0x86, 0x59, 0x30, 0x9e, 0x09, 0x53, 0xc7, 0xc5, 0xf6, 0x77, 0x63, 0xc9, 0x4d, 0x44, 0x58, 0xe0, + 0xd5, 0x17, 0x75, 0x8d, 0x8d, 0x4a, 0xa7, 0xb2, 0xcc, 0x4e, 0x4c, 0x76, 0x0c, 0x47, 0x15, 0x28, + 0x4d, 0x3c, 0x7c, 0x8b, 0x97, 0x4c, 0x68, 0x28, 0x3d, 0x34, 0x41, 0x6b, 0xb7, 0xe3, 0xe6, 0x7a, + 0xee, 0x01, 0x6f, 0xd8, 0xf6, 0x00, 0xb9, 0x87, 0xc7, 0x39, 0xe8, 0x54, 0x1e, 0xec, 0x09, 0x96, + 0x83, 0x37, 0x32, 0x5e, 0x6c, 0x4d, 0x3b, 0x2c, 0x87, 0xf0, 0x10, 0xfb, 0x7d, 0x8a, 0xaa, 0x90, + 0x42, 0x01, 0xd9, 0xc1, 0x4b, 0xac, 0xed, 0x30, 0xc2, 0xe3, 0xd9, 0x5a, 0xd4, 0x37, 0xf5, 0xa8, + 0x53, 0x63, 0xbb, 0x26, 0x88, 0xbb, 0xe9, 0xe1, 0x17, 0xd4, 0x27, 0xa7, 0xae, 0xd3, 0xe1, 0x53, + 0x8c, 0xcf, 0x07, 0x6d, 0x1a, 0x1c, 0xcf, 0xee, 0x37, 0x7c, 0xf5, 0xab, 0x44, 0x76, 0x5d, 0x1a, + 0xc8, 0x5d, 0xc6, 0xc1, 0xe9, 0xc5, 0xad, 0xcc, 0xf0, 0x2b, 0xc2, 0x77, 0x7a, 0xd1, 0xdc, 0x28, + 0x76, 0xf1, 0x72, 0xa7, 0x17, 0xe5, 0xa1, 0xc9, 0xe8, 0x4a, 0xb3, 0xf8, 0x27, 0x9f, 0x6c, 0x77, + 0xc8, 0x87, 0x86, 0xfc, 0xc1, 0x85, 0xe4, 0x16, 0xa7, 0x8d, 0x3e, 0xfb, 0x38, 0xc2, 0x37, 0x0c, + 0x3a, 0xf9, 0x86, 0xf0, 0x52, 0x47, 0x99, 0xd0, 0x7e, 0xbc, 0xff, 0x6e, 0x99, 0xff, 0xe8, 0xf2, + 0x09, 0x16, 0x25, 0x7c, 0xf6, 0xe1, 0xe7, 0x9f, 0xcf, 0xc3, 0x27, 0x64, 0x83, 0xf6, 0xee, 0xb7, + 0x7b, 0x42, 0x45, 0xdf, 0xb9, 0xd3, 0x7b, 0x67, 0x82, 0x33, 0x13, 0x38, 0x13, 0xf9, 0x8e, 0xf0, + 0x72, 0x77, 0xfe, 0xe4, 0xd2, 0x3c, 0xcd, 0x16, 0xf9, 0xd3, 0x2b, 0x64, 0xb8, 0x16, 0x9e, 0x9b, + 0x16, 0xb6, 0xc8, 0xe6, 0xb5, 0x5b, 0x50, 0x9b, 0x5b, 0x3f, 0xe6, 0x01, 0x3a, 0x9d, 0x07, 0xe8, + 0xf7, 0x3c, 0x40, 0x9f, 0x16, 0xc1, 0xe0, 0x74, 0x11, 0x0c, 0x7e, 0x2d, 0x82, 0xc1, 0xcb, 0x75, + 0x9e, 0xe9, 0xb4, 0x4a, 0xa2, 0x7d, 0x99, 0x37, 0x3a, 0xf6, 0xf3, 0x50, 0x1d, 0xbc, 0xa6, 0x6f, + 0x9d, 0xa8, 0x3e, 0x2e, 0x40, 0x25, 0x37, 0xcd, 0x0f, 0xe1, 0xf1, 0xdf, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x92, 0xc3, 0xa0, 0xea, 0x02, 0x05, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // Returns any `Authorization` (or `nil`), with the expiration time, granted to the grantee by the granter for the + // provided msg type. + Authorization(ctx context.Context, in *QueryAuthorizationRequest, opts ...grpc.CallOption) (*QueryAuthorizationResponse, error) + // Returns list of `Authorization`, granted to the grantee by the granter. + Authorizations(ctx context.Context, in *QueryAuthorizationsRequest, opts ...grpc.CallOption) (*QueryAuthorizationsResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) Authorization(ctx context.Context, in *QueryAuthorizationRequest, opts ...grpc.CallOption) (*QueryAuthorizationResponse, error) { + out := new(QueryAuthorizationResponse) + err := c.cc.Invoke(ctx, "/cosmos.authz.v1beta1.Query/Authorization", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Authorizations(ctx context.Context, in *QueryAuthorizationsRequest, opts ...grpc.CallOption) (*QueryAuthorizationsResponse, error) { + out := new(QueryAuthorizationsResponse) + err := c.cc.Invoke(ctx, "/cosmos.authz.v1beta1.Query/Authorizations", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // Returns any `Authorization` (or `nil`), with the expiration time, granted to the grantee by the granter for the + // provided msg type. + Authorization(context.Context, *QueryAuthorizationRequest) (*QueryAuthorizationResponse, error) + // Returns list of `Authorization`, granted to the grantee by the granter. + Authorizations(context.Context, *QueryAuthorizationsRequest) (*QueryAuthorizationsResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) Authorization(ctx context.Context, req *QueryAuthorizationRequest) (*QueryAuthorizationResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Authorization not implemented") +} +func (*UnimplementedQueryServer) Authorizations(ctx context.Context, req *QueryAuthorizationsRequest) (*QueryAuthorizationsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Authorizations not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_Authorization_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAuthorizationRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Authorization(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.authz.v1beta1.Query/Authorization", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Authorization(ctx, req.(*QueryAuthorizationRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Authorizations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAuthorizationsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Authorizations(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.authz.v1beta1.Query/Authorizations", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Authorizations(ctx, req.(*QueryAuthorizationsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cosmos.authz.v1beta1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Authorization", + Handler: _Query_Authorization_Handler, + }, + { + MethodName: "Authorizations", + Handler: _Query_Authorizations_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cosmos/authz/v1beta1/query.proto", +} + +func (m *QueryAuthorizationRequest) 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 *QueryAuthorizationRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAuthorizationRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.MethodName) > 0 { + i -= len(m.MethodName) + copy(dAtA[i:], m.MethodName) + i = encodeVarintQuery(dAtA, i, uint64(len(m.MethodName))) + i-- + dAtA[i] = 0x1a + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Granter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryAuthorizationResponse) 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 *QueryAuthorizationResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAuthorizationResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Authorization != nil { + { + size, err := m.Authorization.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 *QueryAuthorizationsRequest) 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 *QueryAuthorizationsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAuthorizationsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Granter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryAuthorizationsResponse) 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 *QueryAuthorizationsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAuthorizationsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Authorizations) > 0 { + for iNdEx := len(m.Authorizations) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Authorizations[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 encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryAuthorizationRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.MethodName) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAuthorizationResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Authorization != nil { + l = m.Authorization.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAuthorizationsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAuthorizationsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Authorizations) > 0 { + for _, e := range m.Authorizations { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryAuthorizationRequest) 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: QueryAuthorizationRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAuthorizationRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MethodName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MethodName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAuthorizationResponse) 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: QueryAuthorizationResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAuthorizationResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authorization", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Authorization == nil { + m.Authorization = &AuthorizationGrant{} + } + if err := m.Authorization.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAuthorizationsRequest) 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: QueryAuthorizationsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAuthorizationsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAuthorizationsResponse) 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: QueryAuthorizationsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAuthorizationsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authorizations", 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.Authorizations = append(m.Authorizations, &AuthorizationGrant{}) + if err := m.Authorizations[len(m.Authorizations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/authz/types/query.pb.gw.go b/x/authz/types/query.pb.gw.go new file mode 100644 index 000000000000..d1cd24bc0b54 --- /dev/null +++ b/x/authz/types/query.pb.gw.go @@ -0,0 +1,362 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: cosmos/authz/v1beta1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage + +var ( + filter_Query_Authorization_0 = &utilities.DoubleArray{Encoding: map[string]int{"granter": 0, "grantee": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} +) + +func request_Query_Authorization_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAuthorizationRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["granter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "granter") + } + + protoReq.Granter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "granter", err) + } + + val, ok = pathParams["grantee"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "grantee") + } + + protoReq.Grantee, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "grantee", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Authorization_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Authorization(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Authorization_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAuthorizationRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["granter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "granter") + } + + protoReq.Granter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "granter", err) + } + + val, ok = pathParams["grantee"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "grantee") + } + + protoReq.Grantee, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "grantee", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Authorization_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Authorization(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_Authorizations_0 = &utilities.DoubleArray{Encoding: map[string]int{"granter": 0, "grantee": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} +) + +func request_Query_Authorizations_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAuthorizationsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["granter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "granter") + } + + protoReq.Granter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "granter", err) + } + + val, ok = pathParams["grantee"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "grantee") + } + + protoReq.Grantee, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "grantee", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Authorizations_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Authorizations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Authorizations_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAuthorizationsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["granter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "granter") + } + + protoReq.Granter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "granter", err) + } + + val, ok = pathParams["grantee"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "grantee") + } + + protoReq.Grantee, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "grantee", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Authorizations_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Authorizations(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Authorization_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Authorization_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Authorization_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Authorizations_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Authorizations_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Authorizations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_Authorization_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_Authorization_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_Authorization_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Authorizations_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_Authorizations_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_Authorizations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_Authorization_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6, 2, 7}, []string{"cosmos", "authz", "v1beta1", "granters", "granter", "grantees", "grantee", "grant"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_Authorizations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6, 2, 7}, []string{"cosmos", "authz", "v1beta1", "granters", "granter", "grantees", "grantee", "grants"}, "", runtime.AssumeColonVerbOpt(true))) +) + +var ( + forward_Query_Authorization_0 = runtime.ForwardResponseMessage + + forward_Query_Authorizations_0 = runtime.ForwardResponseMessage +) diff --git a/x/authz/types/send_authorization.go b/x/authz/types/send_authorization.go new file mode 100644 index 000000000000..2bb2a63a74f6 --- /dev/null +++ b/x/authz/types/send_authorization.go @@ -0,0 +1,45 @@ +package types + +import ( + "reflect" + + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + bank "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +var ( + _ Authorization = &SendAuthorization{} +) + +// NewSendAuthorization creates a new SendAuthorization object. +func NewSendAuthorization(spendLimit sdk.Coins) *SendAuthorization { + return &SendAuthorization{ + SpendLimit: spendLimit, + } +} + +// MethodName implements Authorization.MethodName. +func (authorization SendAuthorization) MethodName() string { + return "/cosmos.bank.v1beta1.Msg/Send" +} + +// Accept implements Authorization.Accept. +func (authorization SendAuthorization) Accept(msg sdk.ServiceMsg, block tmproto.Header) (allow bool, updated Authorization, delete bool) { + if reflect.TypeOf(msg.Request) == reflect.TypeOf(&bank.MsgSend{}) { + msg, ok := msg.Request.(*bank.MsgSend) + if ok { + limitLeft, isNegative := authorization.SpendLimit.SafeSub(msg.Amount) + if isNegative { + return false, nil, false + } + if limitLeft.IsZero() { + return true, nil, true + } + + return true, &SendAuthorization{SpendLimit: limitLeft}, false + } + } + return false, nil, false +} diff --git a/x/authz/types/tx.pb.go b/x/authz/types/tx.pb.go new file mode 100644 index 000000000000..7705f5d44afc --- /dev/null +++ b/x/authz/types/tx.pb.go @@ -0,0 +1,1609 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/authz/v1beta1/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + types "github.com/cosmos/cosmos-sdk/codec/types" + types1 "github.com/cosmos/cosmos-sdk/types" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" + _ "github.com/golang/protobuf/ptypes/timestamp" + _ "github.com/regen-network/cosmos-proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MsgGrantAuthorizationRequest grants the provided authorization to the grantee on the granter's +// account with the provided expiration time. +type MsgGrantAuthorizationRequest struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` + Authorization *types.Any `protobuf:"bytes,3,opt,name=authorization,proto3" json:"authorization,omitempty"` + Expiration time.Time `protobuf:"bytes,4,opt,name=expiration,proto3,stdtime" json:"expiration"` +} + +func (m *MsgGrantAuthorizationRequest) Reset() { *m = MsgGrantAuthorizationRequest{} } +func (m *MsgGrantAuthorizationRequest) String() string { return proto.CompactTextString(m) } +func (*MsgGrantAuthorizationRequest) ProtoMessage() {} +func (*MsgGrantAuthorizationRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_3ceddab7d8589ad1, []int{0} +} +func (m *MsgGrantAuthorizationRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgGrantAuthorizationRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgGrantAuthorizationRequest.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 *MsgGrantAuthorizationRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgGrantAuthorizationRequest.Merge(m, src) +} +func (m *MsgGrantAuthorizationRequest) XXX_Size() int { + return m.Size() +} +func (m *MsgGrantAuthorizationRequest) XXX_DiscardUnknown() { + xxx_messageInfo_MsgGrantAuthorizationRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgGrantAuthorizationRequest proto.InternalMessageInfo + +func (m *MsgGrantAuthorizationRequest) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *MsgGrantAuthorizationRequest) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *MsgGrantAuthorizationRequest) GetAuthorization() *types.Any { + if m != nil { + return m.Authorization + } + return nil +} + +func (m *MsgGrantAuthorizationRequest) GetExpiration() time.Time { + if m != nil { + return m.Expiration + } + return time.Time{} +} + +// MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse response type. +type MsgExecAuthorizedResponse struct { + Result *types1.Result `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` +} + +func (m *MsgExecAuthorizedResponse) Reset() { *m = MsgExecAuthorizedResponse{} } +func (m *MsgExecAuthorizedResponse) String() string { return proto.CompactTextString(m) } +func (*MsgExecAuthorizedResponse) ProtoMessage() {} +func (*MsgExecAuthorizedResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_3ceddab7d8589ad1, []int{1} +} +func (m *MsgExecAuthorizedResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgExecAuthorizedResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgExecAuthorizedResponse.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 *MsgExecAuthorizedResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgExecAuthorizedResponse.Merge(m, src) +} +func (m *MsgExecAuthorizedResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgExecAuthorizedResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgExecAuthorizedResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgExecAuthorizedResponse proto.InternalMessageInfo + +func (m *MsgExecAuthorizedResponse) GetResult() *types1.Result { + if m != nil { + return m.Result + } + return nil +} + +// MsgExecAuthorizedRequest attempts to execute the provided messages using +// authorizations granted to the grantee. Each message should have only +// one signer corresponding to the granter of the authorization. +type MsgExecAuthorizedRequest struct { + Grantee string `protobuf:"bytes,1,opt,name=grantee,proto3" json:"grantee,omitempty"` + Msgs []*types.Any `protobuf:"bytes,2,rep,name=msgs,proto3" json:"msgs,omitempty"` +} + +func (m *MsgExecAuthorizedRequest) Reset() { *m = MsgExecAuthorizedRequest{} } +func (m *MsgExecAuthorizedRequest) String() string { return proto.CompactTextString(m) } +func (*MsgExecAuthorizedRequest) ProtoMessage() {} +func (*MsgExecAuthorizedRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_3ceddab7d8589ad1, []int{2} +} +func (m *MsgExecAuthorizedRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgExecAuthorizedRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgExecAuthorizedRequest.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 *MsgExecAuthorizedRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgExecAuthorizedRequest.Merge(m, src) +} +func (m *MsgExecAuthorizedRequest) XXX_Size() int { + return m.Size() +} +func (m *MsgExecAuthorizedRequest) XXX_DiscardUnknown() { + xxx_messageInfo_MsgExecAuthorizedRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgExecAuthorizedRequest proto.InternalMessageInfo + +func (m *MsgExecAuthorizedRequest) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *MsgExecAuthorizedRequest) GetMsgs() []*types.Any { + if m != nil { + return m.Msgs + } + return nil +} + +// MsgGrantAuthorizationResponse defines the Msg/MsgGrantAuthorization response type. +type MsgGrantAuthorizationResponse struct { +} + +func (m *MsgGrantAuthorizationResponse) Reset() { *m = MsgGrantAuthorizationResponse{} } +func (m *MsgGrantAuthorizationResponse) String() string { return proto.CompactTextString(m) } +func (*MsgGrantAuthorizationResponse) ProtoMessage() {} +func (*MsgGrantAuthorizationResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_3ceddab7d8589ad1, []int{3} +} +func (m *MsgGrantAuthorizationResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgGrantAuthorizationResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgGrantAuthorizationResponse.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 *MsgGrantAuthorizationResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgGrantAuthorizationResponse.Merge(m, src) +} +func (m *MsgGrantAuthorizationResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgGrantAuthorizationResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgGrantAuthorizationResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgGrantAuthorizationResponse proto.InternalMessageInfo + +// MsgRevokeAuthorizationRequest revokes any authorization with the provided sdk.Msg type on the +// granter's account with that has been granted to the grantee. +type MsgRevokeAuthorizationRequest struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` + MethodName string `protobuf:"bytes,3,opt,name=method_name,json=methodName,proto3" json:"method_name,omitempty"` +} + +func (m *MsgRevokeAuthorizationRequest) Reset() { *m = MsgRevokeAuthorizationRequest{} } +func (m *MsgRevokeAuthorizationRequest) String() string { return proto.CompactTextString(m) } +func (*MsgRevokeAuthorizationRequest) ProtoMessage() {} +func (*MsgRevokeAuthorizationRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_3ceddab7d8589ad1, []int{4} +} +func (m *MsgRevokeAuthorizationRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRevokeAuthorizationRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRevokeAuthorizationRequest.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 *MsgRevokeAuthorizationRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRevokeAuthorizationRequest.Merge(m, src) +} +func (m *MsgRevokeAuthorizationRequest) XXX_Size() int { + return m.Size() +} +func (m *MsgRevokeAuthorizationRequest) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRevokeAuthorizationRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRevokeAuthorizationRequest proto.InternalMessageInfo + +func (m *MsgRevokeAuthorizationRequest) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *MsgRevokeAuthorizationRequest) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *MsgRevokeAuthorizationRequest) GetMethodName() string { + if m != nil { + return m.MethodName + } + return "" +} + +// MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse response type. +type MsgRevokeAuthorizationResponse struct { +} + +func (m *MsgRevokeAuthorizationResponse) Reset() { *m = MsgRevokeAuthorizationResponse{} } +func (m *MsgRevokeAuthorizationResponse) String() string { return proto.CompactTextString(m) } +func (*MsgRevokeAuthorizationResponse) ProtoMessage() {} +func (*MsgRevokeAuthorizationResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_3ceddab7d8589ad1, []int{5} +} +func (m *MsgRevokeAuthorizationResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRevokeAuthorizationResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRevokeAuthorizationResponse.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 *MsgRevokeAuthorizationResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRevokeAuthorizationResponse.Merge(m, src) +} +func (m *MsgRevokeAuthorizationResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgRevokeAuthorizationResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRevokeAuthorizationResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRevokeAuthorizationResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgGrantAuthorizationRequest)(nil), "cosmos.authz.v1beta1.MsgGrantAuthorizationRequest") + proto.RegisterType((*MsgExecAuthorizedResponse)(nil), "cosmos.authz.v1beta1.MsgExecAuthorizedResponse") + proto.RegisterType((*MsgExecAuthorizedRequest)(nil), "cosmos.authz.v1beta1.MsgExecAuthorizedRequest") + proto.RegisterType((*MsgGrantAuthorizationResponse)(nil), "cosmos.authz.v1beta1.MsgGrantAuthorizationResponse") + proto.RegisterType((*MsgRevokeAuthorizationRequest)(nil), "cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest") + proto.RegisterType((*MsgRevokeAuthorizationResponse)(nil), "cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse") +} + +func init() { proto.RegisterFile("cosmos/authz/v1beta1/tx.proto", fileDescriptor_3ceddab7d8589ad1) } + +var fileDescriptor_3ceddab7d8589ad1 = []byte{ + // 521 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xc1, 0x6e, 0xd3, 0x40, + 0x10, 0x8d, 0x93, 0xaa, 0xd0, 0x8d, 0x8a, 0xc4, 0x92, 0x83, 0x63, 0x51, 0xdb, 0x32, 0x97, 0x08, + 0xa9, 0x6b, 0x35, 0xe5, 0xc0, 0xb5, 0x51, 0x11, 0xa7, 0x70, 0xb0, 0xe0, 0xc2, 0x81, 0x6a, 0x9d, + 0x0c, 0x1b, 0xab, 0xb5, 0xd7, 0xf5, 0xae, 0xab, 0xa4, 0x12, 0x12, 0x9f, 0xd0, 0x8f, 0xe1, 0x23, + 0x2a, 0x4e, 0x3d, 0x72, 0x02, 0x94, 0x1c, 0xf8, 0x07, 0x4e, 0x28, 0xbb, 0x1b, 0x48, 0xda, 0x18, + 0x11, 0x89, 0x93, 0x3d, 0x33, 0x6f, 0x66, 0x9e, 0xdf, 0x5b, 0x2f, 0xda, 0x1b, 0x70, 0x91, 0x72, + 0x11, 0xd2, 0x52, 0x8e, 0x2e, 0xc3, 0x8b, 0x83, 0x18, 0x24, 0x3d, 0x08, 0xe5, 0x98, 0xe4, 0x05, + 0x97, 0x1c, 0xb7, 0x74, 0x99, 0xa8, 0x32, 0x31, 0x65, 0xa7, 0xad, 0xb3, 0x27, 0x0a, 0x13, 0x1a, + 0x88, 0x0a, 0x9c, 0x16, 0xe3, 0x8c, 0xeb, 0xfc, 0xfc, 0xcd, 0x64, 0x3d, 0xc6, 0x39, 0x3b, 0x83, + 0x50, 0x45, 0x71, 0xf9, 0x3e, 0x94, 0x49, 0x0a, 0x42, 0xd2, 0x34, 0x37, 0x80, 0xf6, 0x6d, 0x00, + 0xcd, 0x26, 0xa6, 0xf4, 0xc4, 0x30, 0x8c, 0xa9, 0x80, 0x90, 0xc6, 0x83, 0xe4, 0x37, 0xcb, 0x79, + 0xa0, 0x41, 0xc1, 0x0f, 0x0b, 0x3d, 0xee, 0x0b, 0xf6, 0xb2, 0xa0, 0x99, 0x3c, 0x2a, 0xe5, 0x88, + 0x17, 0xc9, 0x25, 0x95, 0x09, 0xcf, 0x22, 0x38, 0x2f, 0x41, 0x48, 0x6c, 0xa3, 0x7b, 0x6c, 0x5e, + 0x84, 0xc2, 0xb6, 0x7c, 0xab, 0xb3, 0x13, 0x2d, 0xc2, 0x3f, 0x15, 0xb0, 0xeb, 0xcb, 0x15, 0xc0, + 0x7d, 0xb4, 0x4b, 0x97, 0x67, 0xd9, 0x0d, 0xdf, 0xea, 0x34, 0xbb, 0x2d, 0xa2, 0xc9, 0x92, 0x05, + 0x59, 0x72, 0x94, 0x4d, 0x7a, 0x0f, 0x3f, 0x7f, 0xda, 0xdf, 0x5d, 0x5d, 0xbd, 0xda, 0x8d, 0x8f, + 0x11, 0x82, 0x71, 0x9e, 0x14, 0x7a, 0xd6, 0x96, 0x9a, 0xe5, 0xdc, 0x99, 0xf5, 0x7a, 0xa1, 0x4c, + 0xef, 0xfe, 0xf5, 0x57, 0xaf, 0x76, 0xf5, 0xcd, 0xb3, 0xa2, 0xa5, 0xbe, 0xe0, 0x0d, 0x6a, 0xf7, + 0x05, 0x7b, 0x31, 0x86, 0xc1, 0x62, 0x19, 0x0c, 0x23, 0x10, 0x39, 0xcf, 0x04, 0xe0, 0xe7, 0x68, + 0xbb, 0x00, 0x51, 0x9e, 0x49, 0xf5, 0x91, 0xcd, 0xae, 0x4f, 0x8c, 0x39, 0x73, 0xf1, 0x88, 0xd2, + 0xcb, 0x88, 0x47, 0x22, 0x85, 0x8b, 0x0c, 0x3e, 0x78, 0x87, 0xec, 0x35, 0x63, 0x6f, 0x69, 0x07, + 0xab, 0xda, 0x01, 0xee, 0xa0, 0xad, 0x54, 0x30, 0x61, 0xd7, 0xfd, 0x46, 0x95, 0x30, 0x91, 0x42, + 0x04, 0x1e, 0xda, 0xab, 0xf0, 0x47, 0x53, 0x0f, 0xa4, 0x02, 0x44, 0x70, 0xc1, 0x4f, 0xe1, 0xbf, + 0x39, 0xe8, 0xa1, 0x66, 0x0a, 0x72, 0xc4, 0x87, 0x27, 0x19, 0x4d, 0x41, 0xf9, 0xb7, 0x13, 0x21, + 0x9d, 0x7a, 0x45, 0x53, 0x08, 0x7c, 0xe4, 0x56, 0x6d, 0xd5, 0xbc, 0xba, 0x3f, 0xeb, 0xa8, 0xd1, + 0x17, 0x0c, 0x7f, 0x40, 0xf8, 0x2e, 0x7b, 0xdc, 0x25, 0xeb, 0x7e, 0x10, 0xf2, 0xb7, 0xa3, 0xe8, + 0x1c, 0x6e, 0xd4, 0x63, 0x9c, 0x3d, 0x47, 0x0f, 0x56, 0xcd, 0xc1, 0xa4, 0x72, 0xcc, 0x5a, 0x17, + 0x9d, 0xf0, 0x9f, 0xf1, 0x66, 0xe5, 0x47, 0x0b, 0x3d, 0x5a, 0xa3, 0x0c, 0xae, 0xe6, 0x5f, 0xed, + 0x9e, 0xf3, 0x6c, 0xb3, 0x26, 0x4d, 0xa1, 0x77, 0x7c, 0x3d, 0x75, 0xad, 0x9b, 0xa9, 0x6b, 0x7d, + 0x9f, 0xba, 0xd6, 0xd5, 0xcc, 0xad, 0xdd, 0xcc, 0xdc, 0xda, 0x97, 0x99, 0x5b, 0x7b, 0xfb, 0x94, + 0x25, 0x72, 0x54, 0xc6, 0x64, 0xc0, 0x53, 0x73, 0x01, 0x99, 0xc7, 0xbe, 0x18, 0x9e, 0x86, 0x63, + 0x73, 0x9f, 0xc9, 0x49, 0x0e, 0x22, 0xde, 0x56, 0xe7, 0xf1, 0xf0, 0x57, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x9d, 0x19, 0xe1, 0xec, 0x04, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // GrantAuthorization grants the provided authorization to the grantee on the granter's + // account with the provided expiration time. + GrantAuthorization(ctx context.Context, in *MsgGrantAuthorizationRequest, opts ...grpc.CallOption) (*MsgGrantAuthorizationResponse, error) + // ExecAuthorized attempts to execute the provided messages using + // authorizations granted to the grantee. Each message should have only + // one signer corresponding to the granter of the authorization. + ExecAuthorized(ctx context.Context, in *MsgExecAuthorizedRequest, opts ...grpc.CallOption) (*MsgExecAuthorizedResponse, error) + // RevokeAuthorization revokes any authorization corresponding to the provided method name on the + // granter's account that has been granted to the grantee. + RevokeAuthorization(ctx context.Context, in *MsgRevokeAuthorizationRequest, opts ...grpc.CallOption) (*MsgRevokeAuthorizationResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) GrantAuthorization(ctx context.Context, in *MsgGrantAuthorizationRequest, opts ...grpc.CallOption) (*MsgGrantAuthorizationResponse, error) { + out := new(MsgGrantAuthorizationResponse) + err := c.cc.Invoke(ctx, "/cosmos.authz.v1beta1.Msg/GrantAuthorization", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) ExecAuthorized(ctx context.Context, in *MsgExecAuthorizedRequest, opts ...grpc.CallOption) (*MsgExecAuthorizedResponse, error) { + out := new(MsgExecAuthorizedResponse) + err := c.cc.Invoke(ctx, "/cosmos.authz.v1beta1.Msg/ExecAuthorized", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) RevokeAuthorization(ctx context.Context, in *MsgRevokeAuthorizationRequest, opts ...grpc.CallOption) (*MsgRevokeAuthorizationResponse, error) { + out := new(MsgRevokeAuthorizationResponse) + err := c.cc.Invoke(ctx, "/cosmos.authz.v1beta1.Msg/RevokeAuthorization", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // GrantAuthorization grants the provided authorization to the grantee on the granter's + // account with the provided expiration time. + GrantAuthorization(context.Context, *MsgGrantAuthorizationRequest) (*MsgGrantAuthorizationResponse, error) + // ExecAuthorized attempts to execute the provided messages using + // authorizations granted to the grantee. Each message should have only + // one signer corresponding to the granter of the authorization. + ExecAuthorized(context.Context, *MsgExecAuthorizedRequest) (*MsgExecAuthorizedResponse, error) + // RevokeAuthorization revokes any authorization corresponding to the provided method name on the + // granter's account that has been granted to the grantee. + RevokeAuthorization(context.Context, *MsgRevokeAuthorizationRequest) (*MsgRevokeAuthorizationResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) GrantAuthorization(ctx context.Context, req *MsgGrantAuthorizationRequest) (*MsgGrantAuthorizationResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GrantAuthorization not implemented") +} +func (*UnimplementedMsgServer) ExecAuthorized(ctx context.Context, req *MsgExecAuthorizedRequest) (*MsgExecAuthorizedResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ExecAuthorized not implemented") +} +func (*UnimplementedMsgServer) RevokeAuthorization(ctx context.Context, req *MsgRevokeAuthorizationRequest) (*MsgRevokeAuthorizationResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RevokeAuthorization not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_GrantAuthorization_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgGrantAuthorizationRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).GrantAuthorization(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.authz.v1beta1.Msg/GrantAuthorization", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).GrantAuthorization(ctx, req.(*MsgGrantAuthorizationRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_ExecAuthorized_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgExecAuthorizedRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).ExecAuthorized(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.authz.v1beta1.Msg/ExecAuthorized", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).ExecAuthorized(ctx, req.(*MsgExecAuthorizedRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_RevokeAuthorization_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgRevokeAuthorizationRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).RevokeAuthorization(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.authz.v1beta1.Msg/RevokeAuthorization", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).RevokeAuthorization(ctx, req.(*MsgRevokeAuthorizationRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cosmos.authz.v1beta1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GrantAuthorization", + Handler: _Msg_GrantAuthorization_Handler, + }, + { + MethodName: "ExecAuthorized", + Handler: _Msg_ExecAuthorized_Handler, + }, + { + MethodName: "RevokeAuthorization", + Handler: _Msg_RevokeAuthorization_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cosmos/authz/v1beta1/tx.proto", +} + +func (m *MsgGrantAuthorizationRequest) 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 *MsgGrantAuthorizationRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgGrantAuthorizationRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n1, err1 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Expiration, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Expiration):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintTx(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x22 + if m.Authorization != nil { + { + size, err := m.Authorization.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintTx(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintTx(dAtA, i, uint64(len(m.Granter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgExecAuthorizedResponse) 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 *MsgExecAuthorizedResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgExecAuthorizedResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Result != nil { + { + size, err := m.Result.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgExecAuthorizedRequest) 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 *MsgExecAuthorizedRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgExecAuthorizedRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Msgs) > 0 { + for iNdEx := len(m.Msgs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Msgs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintTx(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgGrantAuthorizationResponse) 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 *MsgGrantAuthorizationResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgGrantAuthorizationResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgRevokeAuthorizationRequest) 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 *MsgRevokeAuthorizationRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRevokeAuthorizationRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.MethodName) > 0 { + i -= len(m.MethodName) + copy(dAtA[i:], m.MethodName) + i = encodeVarintTx(dAtA, i, uint64(len(m.MethodName))) + i-- + dAtA[i] = 0x1a + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintTx(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintTx(dAtA, i, uint64(len(m.Granter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgRevokeAuthorizationResponse) 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 *MsgRevokeAuthorizationResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRevokeAuthorizationResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgGrantAuthorizationRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Authorization != nil { + l = m.Authorization.Size() + n += 1 + l + sovTx(uint64(l)) + } + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Expiration) + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgExecAuthorizedResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Result != nil { + l = m.Result.Size() + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgExecAuthorizedRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.Msgs) > 0 { + for _, e := range m.Msgs { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgGrantAuthorizationResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgRevokeAuthorizationRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.MethodName) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgRevokeAuthorizationResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgGrantAuthorizationRequest) 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 ErrIntOverflowTx + } + 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: MsgGrantAuthorizationRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgGrantAuthorizationRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authorization", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Authorization == nil { + m.Authorization = &types.Any{} + } + if err := m.Authorization.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiration", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Expiration, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgExecAuthorizedResponse) 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 ErrIntOverflowTx + } + 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: MsgExecAuthorizedResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgExecAuthorizedResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Result == nil { + m.Result = &types1.Result{} + } + if err := m.Result.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgExecAuthorizedRequest) 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 ErrIntOverflowTx + } + 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: MsgExecAuthorizedRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgExecAuthorizedRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Msgs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Msgs = append(m.Msgs, &types.Any{}) + if err := m.Msgs[len(m.Msgs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgGrantAuthorizationResponse) 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 ErrIntOverflowTx + } + 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: MsgGrantAuthorizationResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgGrantAuthorizationResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRevokeAuthorizationRequest) 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 ErrIntOverflowTx + } + 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: MsgRevokeAuthorizationRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRevokeAuthorizationRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MethodName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MethodName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRevokeAuthorizationResponse) 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 ErrIntOverflowTx + } + 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: MsgRevokeAuthorizationResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRevokeAuthorizationResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/bank/client/testutil/cli_helpers.go b/x/bank/client/testutil/cli_helpers.go index 820c668c4558..0f1b848cb755 100644 --- a/x/bank/client/testutil/cli_helpers.go +++ b/x/bank/client/testutil/cli_helpers.go @@ -4,10 +4,8 @@ import ( "context" "fmt" - gogogrpc "github.com/gogo/protobuf/grpc" "github.com/spf13/cobra" "github.com/tendermint/tendermint/libs/cli" - grpc "google.golang.org/grpc" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" @@ -15,6 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/testutil" clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/cli" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -33,38 +32,6 @@ func QueryBalancesExec(clientCtx client.Context, address fmt.Stringer, extraArgs return clitestutil.ExecTestCLICmd(clientCtx, bankcli.GetBalancesCmd(), args) } -// serviceMsgClientConn is an instance of grpc.ClientConn that is used to test building -// transactions with MsgClient's. It is intended to be replaced by the work in -// https://github.com/cosmos/cosmos-sdk/issues/7541 when that is ready. -type serviceMsgClientConn struct { - msgs []sdk.Msg -} - -func (t *serviceMsgClientConn) Invoke(_ context.Context, method string, args, _ interface{}, _ ...grpc.CallOption) error { - req, ok := args.(sdk.MsgRequest) - if !ok { - return fmt.Errorf("%T should implement %T", args, (*sdk.MsgRequest)(nil)) - } - - err := req.ValidateBasic() - if err != nil { - return err - } - - t.msgs = append(t.msgs, sdk.ServiceMsg{ - MethodName: method, - Request: req, - }) - - return nil -} - -func (t *serviceMsgClientConn) NewStream(context.Context, *grpc.StreamDesc, string, ...grpc.CallOption) (grpc.ClientStream, error) { - return nil, fmt.Errorf("not supported") -} - -var _ gogogrpc.ClientConn = &serviceMsgClientConn{} - // newSendTxMsgServiceCmd is just for the purpose of testing ServiceMsg's in an end-to-end case. It is effectively // NewSendTxCmd but using MsgClient. func newSendTxMsgServiceCmd() *cobra.Command { @@ -90,14 +57,14 @@ ignored as it is implied from [from_key_or_address].`, } msg := types.NewMsgSend(clientCtx.GetFromAddress(), toAddr, coins) - svcMsgClientConn := &serviceMsgClientConn{} + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} bankMsgClient := types.NewMsgClient(svcMsgClientConn) _, err = bankMsgClient.Send(context.Background(), msg) if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.msgs...) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } diff --git a/x/bank/simulation/operations.go b/x/bank/simulation/operations.go index 9fcc80f0fe45..40be2feeb4a0 100644 --- a/x/bank/simulation/operations.go +++ b/x/bank/simulation/operations.go @@ -76,7 +76,7 @@ func SimulateMsgSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Operatio return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "invalid transfers"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -217,7 +217,7 @@ func SimulateMsgMultiSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Ope return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "invalid transfers"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } diff --git a/x/distribution/simulation/operations.go b/x/distribution/simulation/operations.go index 09090d1f64d6..b83e6f8a4e4b 100644 --- a/x/distribution/simulation/operations.go +++ b/x/distribution/simulation/operations.go @@ -120,7 +120,7 @@ func SimulateMsgSetWithdrawAddress(ak types.AccountKeeper, bk types.BankKeeper, return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -172,7 +172,7 @@ func SimulateMsgWithdrawDelegatorReward(ak types.AccountKeeper, bk types.BankKee return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -227,7 +227,7 @@ func SimulateMsgWithdrawValidatorCommission(ak types.AccountKeeper, bk types.Ban return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -282,6 +282,6 @@ func SimulateMsgFundCommunityPool(ak types.AccountKeeper, bk types.BankKeeper, k return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } diff --git a/x/gov/simulation/operations.go b/x/gov/simulation/operations.go index 2ea89ca97bb1..d90ca07d5ccc 100644 --- a/x/gov/simulation/operations.go +++ b/x/gov/simulation/operations.go @@ -162,7 +162,7 @@ func SimulateMsgSubmitProposal( return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - opMsg := simtypes.NewOperationMsg(msg, true, "") + opMsg := simtypes.NewOperationMsg(msg, true, "", nil) // get the submitted proposal ID proposalID, err := k.GetProposalID(ctx) @@ -248,7 +248,7 @@ func SimulateMsgDeposit(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Ke return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -311,7 +311,7 @@ func operationSimulateMsgVote(ak types.AccountKeeper, bk types.BankKeeper, k kee return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } diff --git a/x/slashing/simulation/operations.go b/x/slashing/simulation/operations.go index 20acc9e91a88..1c49775cc193 100644 --- a/x/slashing/simulation/operations.go +++ b/x/slashing/simulation/operations.go @@ -115,23 +115,23 @@ func SimulateMsgUnjail(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Kee validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) { if res != nil && err == nil { if info.Tombstoned { - return simtypes.NewOperationMsg(msg, true, ""), nil, errors.New("validator should not have been unjailed if validator tombstoned") + return simtypes.NewOperationMsg(msg, true, "", nil), nil, errors.New("validator should not have been unjailed if validator tombstoned") } if ctx.BlockHeader().Time.Before(info.JailedUntil) { - return simtypes.NewOperationMsg(msg, true, ""), nil, errors.New("validator unjailed while validator still in jail period") + return simtypes.NewOperationMsg(msg, true, "", nil), nil, errors.New("validator unjailed while validator still in jail period") } if validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) { - return simtypes.NewOperationMsg(msg, true, ""), nil, errors.New("validator unjailed even though self-delegation too low") + return simtypes.NewOperationMsg(msg, true, "", nil), nil, errors.New("validator unjailed even though self-delegation too low") } } // msg failed as expected - return simtypes.NewOperationMsg(msg, false, ""), nil, nil + return simtypes.NewOperationMsg(msg, false, "", nil), nil, nil } if err != nil { return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, errors.New(res.Log) } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } diff --git a/x/staking/simulation/operations.go b/x/staking/simulation/operations.go index 0bcb274ed717..d9621bc7321c 100644 --- a/x/staking/simulation/operations.go +++ b/x/staking/simulation/operations.go @@ -173,7 +173,7 @@ func SimulateMsgCreateValidator(ak types.AccountKeeper, bk types.BankKeeper, k k return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -244,7 +244,7 @@ func SimulateMsgEditValidator(ak types.AccountKeeper, bk types.BankKeeper, k kee return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -317,7 +317,7 @@ func SimulateMsgDelegate(ak types.AccountKeeper, bk types.BankKeeper, k keeper.K return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -407,7 +407,7 @@ func SimulateMsgUndelegate(ak types.AccountKeeper, bk types.BankKeeper, k keeper return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -520,6 +520,6 @@ func SimulateMsgBeginRedelegate(ak types.AccountKeeper, bk types.BankKeeper, k k return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } diff --git a/x/staking/types/tx.pb.go b/x/staking/types/tx.pb.go index fad3a8c75e14..50e1765ff6c0 100644 --- a/x/staking/types/tx.pb.go +++ b/x/staking/types/tx.pb.go @@ -6,11 +6,6 @@ package types import ( context "context" fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - time "time" - types "github.com/cosmos/cosmos-sdk/codec/types" github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" types1 "github.com/cosmos/cosmos-sdk/types" @@ -23,6 +18,10 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" + time "time" ) // Reference imports to suppress errors if they are not otherwise used. From 50b4be91108784197aa6b311257f0256cdd1e67f Mon Sep 17 00:00:00 2001 From: vincent Date: Tue, 26 Jan 2021 17:32:05 +0800 Subject: [PATCH 077/152] Fix query signing infos command (#8427) * fix query signing infos command * add changelog --- CHANGELOG.md | 1 + x/slashing/client/cli/query.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7bf603d7813..fd4aa4a1387c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes +* (x/slashing) [\#8427](https://github.com/cosmos/cosmos-sdk/pull/8427) Fix query signing infos command * (simapp) [\#8418](https://github.com/cosmos/cosmos-sdk/pull/8418) Add balance coin to supply when adding a new genesis account * (x/bank) [\#8417](https://github.com/cosmos/cosmos-sdk/pull/8417) Validate balances and coin denom metadata on genesis * (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value diff --git a/x/slashing/client/cli/query.go b/x/slashing/client/cli/query.go index b6b71a344cd3..d55b33201b10 100644 --- a/x/slashing/client/cli/query.go +++ b/x/slashing/client/cli/query.go @@ -81,7 +81,7 @@ func GetCmdQuerySigningInfos() *cobra.Command { $ query slashing signing-infos `), - Args: cobra.ExactArgs(1), + Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientQueryContext(cmd) if err != nil { From 09b8f7783ab3bf147335cc9c58459186a6cd84a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Tue, 26 Jan 2021 13:03:21 +0100 Subject: [PATCH 078/152] ibc: MsgTransfer amino JSON, commits from @fedekunze (#8437) --- CHANGELOG.md | 4 ++++ x/auth/client/rest/rest_test.go | 3 +-- x/ibc/applications/transfer/module.go | 4 +++- x/ibc/applications/transfer/types/codec.go | 18 +++++++++++++++++- x/ibc/applications/transfer/types/msgs.go | 5 ++--- x/ibc/applications/transfer/types/msgs_test.go | 10 ++++++++++ 6 files changed, 37 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd4aa4a1387c..75f7adb0b421 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### State Machine Breaking + +* (x/ibc) [\#8266](https://github.com/cosmos/cosmos-sdk/issues/8266) Add amino JSON for IBC messages in order to support Ledger text signing. + ### Improvements * (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks. diff --git a/x/auth/client/rest/rest_test.go b/x/auth/client/rest/rest_test.go index d485467249a5..1196e52e4a68 100644 --- a/x/auth/client/rest/rest_test.go +++ b/x/auth/client/rest/rest_test.go @@ -186,8 +186,7 @@ func (s *IntegrationTestSuite) TestBroadcastIBCTxRequest() { res, err := rest.PostRequest(fmt.Sprintf("%s/txs", val.APIAddress), "application/json", []byte(req)) s.Require().NoError(err) - // Make sure the error message is correct. - s.Require().Contains(string(res), "this transaction cannot be broadcasted via legacy REST endpoints") + s.Require().NotContains(string(res), "this transaction cannot be broadcasted via legacy REST endpoints", string(res)) } // Helper function to test querying txs. We will use it to query StdTx and service `Msg`s. diff --git a/x/ibc/applications/transfer/module.go b/x/ibc/applications/transfer/module.go index bf324e2c9b36..039597afe5e4 100644 --- a/x/ibc/applications/transfer/module.go +++ b/x/ibc/applications/transfer/module.go @@ -46,7 +46,9 @@ func (AppModuleBasic) Name() string { } // RegisterLegacyAminoCodec implements AppModuleBasic interface -func (AppModuleBasic) RegisterLegacyAminoCodec(*codec.LegacyAmino) {} +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} // RegisterInterfaces registers module concrete types into protobuf Any. func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { diff --git a/x/ibc/applications/transfer/types/codec.go b/x/ibc/applications/transfer/types/codec.go index 18b594f8a77a..24ad7e5a9023 100644 --- a/x/ibc/applications/transfer/types/codec.go +++ b/x/ibc/applications/transfer/types/codec.go @@ -7,6 +7,12 @@ import ( "github.com/cosmos/cosmos-sdk/types/msgservice" ) +// RegisterLegacyAminoCodec registers the necessary x/ibc transfer interfaces and concrete types +// on the provided LegacyAmino codec. These types are used for Amino JSON serialization. +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(&MsgTransfer{}, "cosmos-sdk/MsgTransfer", nil) +} + // RegisterInterfaces register the ibc transfer module interfaces to protobuf // Any. func RegisterInterfaces(registry codectypes.InterfaceRegistry) { @@ -16,10 +22,20 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { } var ( + amino = codec.NewLegacyAmino() + // ModuleCdc references the global x/ibc-transfer module codec. Note, the codec // should ONLY be used in certain instances of tests and for JSON encoding. // - // The actual codec used for serialization should be provided to x/ibc-transfer and + // The actual codec used for serialization should be provided to x/ibc transfer and // defined at the application level. ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) + + // AminoCdc is a amino codec created to support amino json compatible msgs. + AminoCdc = codec.NewAminoCodec(amino) ) + +func init() { + RegisterLegacyAminoCodec(amino) + amino.Seal() +} diff --git a/x/ibc/applications/transfer/types/msgs.go b/x/ibc/applications/transfer/types/msgs.go index 065482671375..cf2293213a82 100644 --- a/x/ibc/applications/transfer/types/msgs.go +++ b/x/ibc/applications/transfer/types/msgs.go @@ -70,10 +70,9 @@ func (msg MsgTransfer) ValidateBasic() error { return ValidateIBCDenom(msg.Token.Denom) } -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. +// GetSignBytes implements sdk.Msg. func (msg MsgTransfer) GetSignBytes() []byte { - panic("IBC messages do not support amino") + return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg)) } // GetSigners implements sdk.Msg diff --git a/x/ibc/applications/transfer/types/msgs_test.go b/x/ibc/applications/transfer/types/msgs_test.go index 89bd39524a51..1fc70c543bbe 100644 --- a/x/ibc/applications/transfer/types/msgs_test.go +++ b/x/ibc/applications/transfer/types/msgs_test.go @@ -1,6 +1,7 @@ package types import ( + "fmt" "testing" "github.com/stretchr/testify/require" @@ -51,6 +52,15 @@ func TestMsgTransferType(t *testing.T) { require.Equal(t, "transfer", msg.Type()) } +func TestMsgTransferGetSignBytes(t *testing.T) { + msg := NewMsgTransfer(validPort, validChannel, coin, addr1, addr2, timeoutHeight, 0) + expected := fmt.Sprintf(`{"type":"cosmos-sdk/MsgTransfer","value":{"receiver":"%s","sender":"%s","source_channel":"testchannel","source_port":"testportid","timeout_height":{"revision_height":"10"},"token":{"amount":"100","denom":"atom"}}}`, addr2, addr1) + require.NotPanics(t, func() { + res := msg.GetSignBytes() + require.Equal(t, expected, string(res)) + }) +} + // TestMsgTransferValidation tests ValidateBasic for MsgTransfer func TestMsgTransferValidation(t *testing.T) { testCases := []struct { From ce11c9043e9b483fcdb520ee31e3f3b5a68fbe17 Mon Sep 17 00:00:00 2001 From: Marko Date: Wed, 27 Jan 2021 10:08:18 +0000 Subject: [PATCH 079/152] avoid login when in PR (#8449) --- .github/workflows/docker.yml | 1 + .github/workflows/proto-docker.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 9456ebf30255..6116e6d92107 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -42,6 +42,7 @@ jobs: uses: docker/setup-buildx-action@v1 - name: Login to DockerHub + if: ${{ github.event_name != 'pull_request' }} uses: docker/login-action@v1 with: username: ${{ secrets.DOCKER_USERNAME }} diff --git a/.github/workflows/proto-docker.yml b/.github/workflows/proto-docker.yml index b127de0a5874..7a9aecfb25ee 100644 --- a/.github/workflows/proto-docker.yml +++ b/.github/workflows/proto-docker.yml @@ -31,6 +31,7 @@ jobs: uses: docker/setup-buildx-action@v1 - name: Login to DockerHub + if: ${{ github.event_name != 'pull_request' }} uses: docker/login-action@v1 with: username: ${{ secrets.DOCKERHUBTM_USERNAME }} From fd04f41e234c9bbcef4f4fb4b7204c032d4eaddf Mon Sep 17 00:00:00 2001 From: Jun Kimura Date: Wed, 27 Jan 2021 19:19:04 +0900 Subject: [PATCH 080/152] ibc-transfer: fix non-deterministic attribute value (#8442) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- x/ibc/applications/transfer/module.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/ibc/applications/transfer/module.go b/x/ibc/applications/transfer/module.go index 039597afe5e4..900526f583b7 100644 --- a/x/ibc/applications/transfer/module.go +++ b/x/ibc/applications/transfer/module.go @@ -379,7 +379,7 @@ func (am AppModule) OnAcknowledgementPacket( sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), sdk.NewAttribute(types.AttributeKeyDenom, data.Denom), sdk.NewAttribute(types.AttributeKeyAmount, fmt.Sprintf("%d", data.Amount)), - sdk.NewAttribute(types.AttributeKeyAck, fmt.Sprintf("%v", ack)), + sdk.NewAttribute(types.AttributeKeyAck, ack.String()), ), ) From e2f510afcc3478edab4a7d8d786dccbec333dddd Mon Sep 17 00:00:00 2001 From: Riccardo Montagnin Date: Wed, 27 Jan 2021 12:07:45 +0100 Subject: [PATCH 081/152] Compatibility with the ARM architecture (#8396) Co-authored-by: Alessio Treglia Co-authored-by: Jonathan Gimeno --- .github/workflows/test.yml | 20 ++++++++++++++++++++ CHANGELOG.md | 1 + Makefile | 2 +- snapshots/store.go | 6 +++--- store/rootmulti/store.go | 4 ++-- x/ibc/applications/transfer/module.go | 4 ++-- x/ibc/core/02-client/types/client.go | 2 +- 7 files changed, 30 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d8f051e60cb7..dd09041862d3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,6 +31,26 @@ jobs: path: ~/go/bin key: ${{ runner.os }}-go-tparse-binary + build: + runs-on: ubuntu-latest + strategy: + matrix: + go-arch: ["amd64", "arm", "arm64"] + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2.1.3 + with: + go-version: 1.15 + - uses: technote-space/get-diff-action@v4 + id: git_diff + with: + PATTERNS: | + **/**.go + go.mod + go.sum + - name: Build + run: GOARCH=${{ matrix.go-arch }} LEDGER_ENABLED=false make build + test-cosmovisor: runs-on: ubuntu-latest steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index 75f7adb0b421..0ea84cb3475f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements * (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks. +* [\#8396](https://github.com/cosmos/cosmos-sdk/pull/8396) Add support for ARM platform ### Bug Fixes diff --git a/Makefile b/Makefile index 0f4cf9e80fb2..f49f95e73449 100644 --- a/Makefile +++ b/Makefile @@ -479,4 +479,4 @@ rosetta-data: docker run --name data_dir_build -t rosetta-ci:latest sh /rosetta/data.sh docker cp data_dir_build:/tmp/data.tar.gz "$(CURDIR)/contrib/rosetta/node/data.tar.gz" docker container rm data_dir_build -.PHONY: rosetta-data \ No newline at end of file +.PHONY: rosetta-data diff --git a/snapshots/store.go b/snapshots/store.go index e0bcbe6bd570..77ff58e22ff6 100644 --- a/snapshots/store.go +++ b/snapshots/store.go @@ -91,7 +91,7 @@ func (s *Store) Get(height uint64, format uint32) (*types.Snapshot, error) { // Get fetches the latest snapshot from the database, if any. func (s *Store) GetLatest() (*types.Snapshot, error) { - iter, err := s.db.ReverseIterator(encodeKey(0, 0), encodeKey(math.MaxUint64, math.MaxUint32)) + iter, err := s.db.ReverseIterator(encodeKey(0, 0), encodeKey(uint64(math.MaxUint64), math.MaxUint32)) if err != nil { return nil, sdkerrors.Wrap(err, "failed to find latest snapshot") } @@ -111,7 +111,7 @@ func (s *Store) GetLatest() (*types.Snapshot, error) { // List lists snapshots, in reverse order (newest first). func (s *Store) List() ([]*types.Snapshot, error) { - iter, err := s.db.ReverseIterator(encodeKey(0, 0), encodeKey(math.MaxUint64, math.MaxUint32)) + iter, err := s.db.ReverseIterator(encodeKey(0, 0), encodeKey(uint64(math.MaxUint64), math.MaxUint32)) if err != nil { return nil, sdkerrors.Wrap(err, "failed to list snapshots") } @@ -181,7 +181,7 @@ func (s *Store) loadChunkFile(height uint64, format uint32, chunk uint32) (io.Re // Prune removes old snapshots. The given number of most recent heights (regardless of format) are retained. func (s *Store) Prune(retain uint32) (uint64, error) { - iter, err := s.db.ReverseIterator(encodeKey(0, 0), encodeKey(math.MaxUint64, math.MaxUint32)) + iter, err := s.db.ReverseIterator(encodeKey(0, 0), encodeKey(uint64(math.MaxUint64), math.MaxUint32)) if err != nil { return 0, sdkerrors.Wrap(err, "failed to prune snapshots") } diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index 03fa1b561fdb..0e8cba44ef5e 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -711,9 +711,9 @@ func (rs *Store) Restore( if height == 0 { return sdkerrors.Wrap(sdkerrors.ErrLogic, "cannot restore snapshot at height 0") } - if height > math.MaxInt64 { + if height > uint64(math.MaxUint64) { return sdkerrors.Wrapf(snapshottypes.ErrInvalidMetadata, - "snapshot height %v cannot exceed %v", height, math.MaxInt64) + "snapshot height %v cannot exceed %v", height, int64(math.MaxInt64)) } // Signal readiness. Must be done before the readers below are set up, since the zlib diff --git a/x/ibc/applications/transfer/module.go b/x/ibc/applications/transfer/module.go index 900526f583b7..67c736555b8a 100644 --- a/x/ibc/applications/transfer/module.go +++ b/x/ibc/applications/transfer/module.go @@ -202,8 +202,8 @@ func ValidateTransferChannelParams( if err != nil { return err } - if channelSequence > math.MaxUint32 { - return sdkerrors.Wrapf(types.ErrMaxTransferChannels, "channel sequence %d is greater than max allowed transfer channels %d", channelSequence, math.MaxUint32) + if channelSequence > uint64(math.MaxUint32) { + return sdkerrors.Wrapf(types.ErrMaxTransferChannels, "channel sequence %d is greater than max allowed transfer channels %d", channelSequence, uint64(math.MaxUint32)) } if order != channeltypes.UNORDERED { return sdkerrors.Wrapf(channeltypes.ErrInvalidChannelOrdering, "expected %s channel, got %s ", channeltypes.UNORDERED, order) diff --git a/x/ibc/core/02-client/types/client.go b/x/ibc/core/02-client/types/client.go index 1c44d6e2b9c2..6d51828af0f7 100644 --- a/x/ibc/core/02-client/types/client.go +++ b/x/ibc/core/02-client/types/client.go @@ -93,7 +93,7 @@ func ValidateClientType(clientType string) error { } smallestPossibleClientID := FormatClientIdentifier(clientType, 0) - largestPossibleClientID := FormatClientIdentifier(clientType, math.MaxUint64) + largestPossibleClientID := FormatClientIdentifier(clientType, uint64(math.MaxUint64)) // IsValidClientID will check client type format and if the sequence is a uint64 if !IsValidClientID(smallestPossibleClientID) { From 580e9681a5eb41773cad73ea03647e7253704fed Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Wed, 27 Jan 2021 22:40:56 -0800 Subject: [PATCH 082/152] types: use proper lowercase syntax for coins in benchmarks (#8435) Instead of COINZ_%d use coinZ%d which is the syntax accepted by types.ParseCoin, to generate coins to use in benchmarking. Fixes #8433 --- types/coin_benchmark_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/coin_benchmark_test.go b/types/coin_benchmark_test.go index fc73afe87aaa..bfc2bfe99cde 100644 --- a/types/coin_benchmark_test.go +++ b/types/coin_benchmark_test.go @@ -6,7 +6,7 @@ import ( ) func coinName(suffix int) string { - return fmt.Sprintf("COINZ_%d", suffix) + return fmt.Sprintf("coinz%d", suffix) } func BenchmarkCoinsAdditionIntersect(b *testing.B) { From 784a9a69a160d805fffd7fa945c281f8cdcf19d3 Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Wed, 27 Jan 2021 23:52:08 -0800 Subject: [PATCH 083/152] all: ensure b.ReportAllocs() in all the benchmarks (#8460) With this change, we'll get details on the number of allocations performed by code. Later on when we have continuous benchmarking infrastructure, this change will prove useful to flag regressions. Fixes #8459 Co-authored-by: Alessio Treglia --- crypto/armor_test.go | 2 ++ crypto/keys/internal/benchmarking/bench.go | 1 + crypto/keys/secp256k1/bench_test.go | 3 +++ simapp/sim_bench_test.go | 2 ++ store/cache/benchmark_test.go | 1 + store/cachekv/store_bench_test.go | 1 + store/cachekv/store_test.go | 2 ++ store/iavl/store_test.go | 1 + store/rootmulti/store_test.go | 2 ++ types/address_bench_test.go | 2 ++ types/coin_benchmark_test.go | 2 ++ types/decimal_test.go | 1 + x/auth/keeper/keeper_bench_test.go | 1 + x/bank/bench_test.go | 1 + x/mint/types/minter_test.go | 3 +++ 15 files changed, 25 insertions(+) diff --git a/crypto/armor_test.go b/crypto/armor_test.go index abbc7870aaee..70854f6dcb41 100644 --- a/crypto/armor_test.go +++ b/crypto/armor_test.go @@ -158,6 +158,8 @@ func TestUnarmorInfoBytesErrors(t *testing.T) { } func BenchmarkBcryptGenerateFromPassword(b *testing.B) { + b.ReportAllocs() + passphrase := []byte("passphrase") for securityParam := 9; securityParam < 16; securityParam++ { param := securityParam diff --git a/crypto/keys/internal/benchmarking/bench.go b/crypto/keys/internal/benchmarking/bench.go index a789da91f9c9..a55936d5c3c8 100644 --- a/crypto/keys/internal/benchmarking/bench.go +++ b/crypto/keys/internal/benchmarking/bench.go @@ -25,6 +25,7 @@ func (zeroReader) Read(buf []byte) (int, error) { // BenchmarkKeyGeneration benchmarks the given key generation algorithm using // a dummy reader. func BenchmarkKeyGeneration(b *testing.B, generateKey func(reader io.Reader) types.PrivKey) { + b.ReportAllocs() var zero zeroReader for i := 0; i < b.N; i++ { generateKey(zero) diff --git a/crypto/keys/secp256k1/bench_test.go b/crypto/keys/secp256k1/bench_test.go index 423f7a5a52de..a9f694de7552 100644 --- a/crypto/keys/secp256k1/bench_test.go +++ b/crypto/keys/secp256k1/bench_test.go @@ -9,6 +9,7 @@ import ( ) func BenchmarkKeyGeneration(b *testing.B) { + b.ReportAllocs() benchmarkKeygenWrapper := func(reader io.Reader) types.PrivKey { priv := genPrivKey(reader) return &PrivKey{Key: priv} @@ -17,11 +18,13 @@ func BenchmarkKeyGeneration(b *testing.B) { } func BenchmarkSigning(b *testing.B) { + b.ReportAllocs() priv := GenPrivKey() benchmarking.BenchmarkSigning(b, priv) } func BenchmarkVerification(b *testing.B) { + b.ReportAllocs() priv := GenPrivKey() benchmarking.BenchmarkVerification(b, priv) } diff --git a/simapp/sim_bench_test.go b/simapp/sim_bench_test.go index 7c22dcfe8a44..ba5c71c6f3fb 100644 --- a/simapp/sim_bench_test.go +++ b/simapp/sim_bench_test.go @@ -14,6 +14,7 @@ import ( // Profile with: // /usr/local/go/bin/go test -benchmem -run=^$ github.com/cosmos/cosmos-sdk/simapp -bench ^BenchmarkFullAppSimulation$ -Commit=true -cpuprofile cpu.out func BenchmarkFullAppSimulation(b *testing.B) { + b.ReportAllocs() config, db, dir, logger, _, err := SetupSimulation("goleveldb-app-sim", "Simulation") if err != nil { b.Fatalf("simulation setup failed: %s", err.Error()) @@ -57,6 +58,7 @@ func BenchmarkFullAppSimulation(b *testing.B) { } func BenchmarkInvariants(b *testing.B) { + b.ReportAllocs() config, db, dir, logger, _, err := SetupSimulation("leveldb-app-invariant-bench", "Simulation") if err != nil { b.Fatalf("simulation setup failed: %s", err.Error()) diff --git a/store/cache/benchmark_test.go b/store/cache/benchmark_test.go index cf8206272c41..10b5da2bfb0b 100644 --- a/store/cache/benchmark_test.go +++ b/store/cache/benchmark_test.go @@ -22,6 +22,7 @@ func populate(mgr *CommitKVStoreCacheManager) { } func BenchmarkReset(b *testing.B) { + b.ReportAllocs() mgr := freshMgr() b.ResetTimer() diff --git a/store/cachekv/store_bench_test.go b/store/cachekv/store_bench_test.go index 4902819834d8..2957fe6a6503 100644 --- a/store/cachekv/store_bench_test.go +++ b/store/cachekv/store_bench_test.go @@ -12,6 +12,7 @@ import ( ) func benchmarkCacheKVStoreIterator(numKVs int, b *testing.B) { + b.ReportAllocs() mem := dbadapter.Store{DB: dbm.NewMemDB()} cstore := cachekv.NewStore(mem) keys := make([]string, numKVs) diff --git a/store/cachekv/store_test.go b/store/cachekv/store_test.go index e3b33341b8c4..0404f33f2a28 100644 --- a/store/cachekv/store_test.go +++ b/store/cachekv/store_test.go @@ -516,6 +516,7 @@ func (krc *keyRangeCounter) key() int { func bz(s string) []byte { return []byte(s) } func BenchmarkCacheKVStoreGetNoKeyFound(b *testing.B) { + b.ReportAllocs() st := newCacheKVStore() b.ResetTimer() // assumes b.N < 2**24 @@ -525,6 +526,7 @@ func BenchmarkCacheKVStoreGetNoKeyFound(b *testing.B) { } func BenchmarkCacheKVStoreGetKeyFound(b *testing.B) { + b.ReportAllocs() st := newCacheKVStore() for i := 0; i < b.N; i++ { arr := []byte{byte((i & 0xFF0000) >> 16), byte((i & 0xFF00) >> 8), byte(i & 0xFF)} diff --git a/store/iavl/store_test.go b/store/iavl/store_test.go index 790830038ba9..cfda5efacf37 100644 --- a/store/iavl/store_test.go +++ b/store/iavl/store_test.go @@ -556,6 +556,7 @@ func TestIAVLStoreQuery(t *testing.T) { } func BenchmarkIAVLIteratorNext(b *testing.B) { + b.ReportAllocs() db := dbm.NewMemDB() treeSize := 1000 tree, err := iavl.NewMutableTree(db, cacheSize) diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index e4654f410d0d..eafc0d6bb817 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -689,6 +689,7 @@ func BenchmarkMultistoreSnapshotRestore1M(b *testing.B) { } func benchmarkMultistoreSnapshot(b *testing.B, stores uint8, storeKeys uint64) { + b.ReportAllocs() b.StopTimer() source := newMultiStoreWithGeneratedData(dbm.NewMemDB(), stores, storeKeys) version := source.LastCommitID().Version @@ -716,6 +717,7 @@ func benchmarkMultistoreSnapshot(b *testing.B, stores uint8, storeKeys uint64) { } func benchmarkMultistoreSnapshotRestore(b *testing.B, stores uint8, storeKeys uint64) { + b.ReportAllocs() b.StopTimer() source := newMultiStoreWithGeneratedData(dbm.NewMemDB(), stores, storeKeys) version := uint64(source.LastCommitID().Version) diff --git a/types/address_bench_test.go b/types/address_bench_test.go index 59222dacf9b7..88a7e537a0d2 100644 --- a/types/address_bench_test.go +++ b/types/address_bench_test.go @@ -12,6 +12,7 @@ import ( ) func BenchmarkBech32ifyPubKey(b *testing.B) { + b.ReportAllocs() pkBz := make([]byte, ed25519.PubKeySize) pk := &ed25519.PubKey{Key: pkBz} rng := rand.New(rand.NewSource(time.Now().Unix())) @@ -29,6 +30,7 @@ func BenchmarkBech32ifyPubKey(b *testing.B) { } func BenchmarkGetPubKeyFromBech32(b *testing.B) { + b.ReportAllocs() pkBz := make([]byte, ed25519.PubKeySize) pk := &ed25519.PubKey{Key: pkBz} rng := rand.New(rand.NewSource(time.Now().Unix())) diff --git a/types/coin_benchmark_test.go b/types/coin_benchmark_test.go index bfc2bfe99cde..c6e040112115 100644 --- a/types/coin_benchmark_test.go +++ b/types/coin_benchmark_test.go @@ -10,6 +10,7 @@ func coinName(suffix int) string { } func BenchmarkCoinsAdditionIntersect(b *testing.B) { + b.ReportAllocs() benchmarkingFunc := func(numCoinsA int, numCoinsB int) func(b *testing.B) { return func(b *testing.B) { coinsA := Coins(make([]Coin, numCoinsA)) @@ -39,6 +40,7 @@ func BenchmarkCoinsAdditionIntersect(b *testing.B) { } func BenchmarkCoinsAdditionNoIntersect(b *testing.B) { + b.ReportAllocs() benchmarkingFunc := func(numCoinsA int, numCoinsB int) func(b *testing.B) { return func(b *testing.B) { coinsA := Coins(make([]Coin, numCoinsA)) diff --git a/types/decimal_test.go b/types/decimal_test.go index ffd09afc2707..8e62275a0eba 100644 --- a/types/decimal_test.go +++ b/types/decimal_test.go @@ -487,6 +487,7 @@ func (s *decimalTestSuite) TestOperationOrders() { } func BenchmarkMarshalTo(b *testing.B) { + b.ReportAllocs() bis := []struct { in sdk.Dec want []byte diff --git a/x/auth/keeper/keeper_bench_test.go b/x/auth/keeper/keeper_bench_test.go index a217eddacae3..1a18dff84557 100644 --- a/x/auth/keeper/keeper_bench_test.go +++ b/x/auth/keeper/keeper_bench_test.go @@ -7,6 +7,7 @@ import ( ) func BenchmarkAccountMapperGetAccountFound(b *testing.B) { + b.ReportAllocs() app, ctx := createTestApp(false) // assumes b.N < 2**24 diff --git a/x/bank/bench_test.go b/x/bank/bench_test.go index f1affb9d99b8..0648b3b62725 100644 --- a/x/bank/bench_test.go +++ b/x/bank/bench_test.go @@ -18,6 +18,7 @@ import ( var moduleAccAddr = authtypes.NewModuleAddress(stakingtypes.BondedPoolName) func BenchmarkOneBankSendTxPerBlock(b *testing.B) { + b.ReportAllocs() // Add an account at genesis acc := authtypes.BaseAccount{ Address: addr1.String(), diff --git a/x/mint/types/minter_test.go b/x/mint/types/minter_test.go index 8760a66f4466..4abedb51cd05 100644 --- a/x/mint/types/minter_test.go +++ b/x/mint/types/minter_test.go @@ -89,6 +89,7 @@ func TestBlockProvision(t *testing.T) { // using sdk.Dec operations: (current implementation) // BenchmarkBlockProvision-4 3000000 429 ns/op func BenchmarkBlockProvision(b *testing.B) { + b.ReportAllocs() minter := InitialMinter(sdk.NewDecWithPrec(1, 1)) params := DefaultParams() @@ -105,6 +106,7 @@ func BenchmarkBlockProvision(b *testing.B) { // Next inflation benchmarking // BenchmarkNextInflation-4 1000000 1828 ns/op func BenchmarkNextInflation(b *testing.B) { + b.ReportAllocs() minter := InitialMinter(sdk.NewDecWithPrec(1, 1)) params := DefaultParams() bondedRatio := sdk.NewDecWithPrec(1, 1) @@ -119,6 +121,7 @@ func BenchmarkNextInflation(b *testing.B) { // Next annual provisions benchmarking // BenchmarkNextAnnualProvisions-4 5000000 251 ns/op func BenchmarkNextAnnualProvisions(b *testing.B) { + b.ReportAllocs() minter := InitialMinter(sdk.NewDecWithPrec(1, 1)) params := DefaultParams() totalSupply := sdk.NewInt(100000000000000) From 034d14048856940877be4edb356ae729308f1ca9 Mon Sep 17 00:00:00 2001 From: Rikard Hjort Date: Thu, 28 Jan 2021 17:59:51 +0100 Subject: [PATCH 084/152] Misc documentation fixes (#8452) * EndBlock: "beginning" => "end" * misc fixes * beginning => end * fix error in run-node tutorial * Use correct keyring backend when interacting * multiply stakes by 1000 * query accounts with the bank submodule, not accounts * specify key backend for transactions Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/building-modules/beginblock-endblock.md | 2 +- docs/building-modules/module-manager.md | 5 +++-- docs/run-node/interact-node.md | 8 ++++---- docs/run-node/run-node.md | 4 ++-- docs/run-node/txs.md | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/building-modules/beginblock-endblock.md b/docs/building-modules/beginblock-endblock.md index 09a48df8807a..cb8dbba1dda2 100644 --- a/docs/building-modules/beginblock-endblock.md +++ b/docs/building-modules/beginblock-endblock.md @@ -24,7 +24,7 @@ The actual implementation of `BeginBlocker` and `EndBlocker` in `./abci.go` are A specificity of the `EndBlocker` is that it can return validator updates to the underlying consensus engine in the form of an [`[]abci.ValidatorUpdates`](https://tendermint.com/docs/app-dev/abci-spec.html#validatorupdate). This is the preferred way to implement custom validator changes. -It is possible for developers to defined the order of execution between the `BeginBlocker`/`EndBlocker` functions of each of their application's modules via the module's manager `SetOrderBeginBlocker`/`SetOrderEndBlocker` methods. For more on the module manager, click [here](./module-manager.md#manager). +It is possible for developers to define the order of execution between the `BeginBlocker`/`EndBlocker` functions of each of their application's modules via the module's manager `SetOrderBeginBlocker`/`SetOrderEndBlocker` methods. For more on the module manager, click [here](./module-manager.md#manager). See an example implementation of `BeginBlocker` from the `distr` module: diff --git a/docs/building-modules/module-manager.md b/docs/building-modules/module-manager.md index cd8cc4b9eca0..919ec1425c84 100644 --- a/docs/building-modules/module-manager.md +++ b/docs/building-modules/module-manager.md @@ -74,7 +74,8 @@ Let us go through the methods of `AppModule`: - `LegacyQuerierHandler(*codec.LegacyAmino)` (deprecated): Returns a [`querier`](./query-services.md#legacy-queriers) given the query `path`, in order to process the `query`. - `RegisterServices(Configurator)`: Allows a module to register services. - `BeginBlock(sdk.Context, abci.RequestBeginBlock)`: This method gives module developers the option to implement logic that is automatically triggered at the beginning of each block. Implement empty if no logic needs to be triggered at the beginning of each block for this module. -- `EndBlock(sdk.Context, abci.RequestEndBlock)`: This method gives module developers the option to implement logic that is automatically triggered at the beginning of each block. This is also where the module can inform the underlying consensus engine of validator set changes (e.g. the `staking` module). Implement empty if no logic needs to be triggered at the beginning of each block for this module. +- `EndBlock(sdk.Context, abci.RequestEndBlock)`: This method gives module developers the option to implement logic that is automatically triggered at the end of each block. This is also where the module can inform the underlying consensus engine of validator set changes (e.g. the `staking` module). Implement empty if no logic needs to be triggered at the end of each block for this module. + ### Implementing the Application Module Interfaces @@ -132,7 +133,7 @@ The module manager is used throughout the application whenever an action on a co - `SetOrderInitGenesis(moduleNames ...string)`: Sets the order in which the [`InitGenesis`](./genesis.md#initgenesis) function of each module will be called when the application is first started. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). - `SetOrderExportGenesis(moduleNames ...string)`: Sets the order in which the [`ExportGenesis`](./genesis.md#exportgenesis) function of each module will be called in case of an export. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). - `SetOrderBeginBlockers(moduleNames ...string)`: Sets the order in which the `BeginBlock()` function of each module will be called at the beginning of each block. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). -- `SetOrderEndBlockers(moduleNames ...string)`: Sets the order in which the `EndBlock()` function of each module will be called at the beginning of each block. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). +- `SetOrderEndBlockers(moduleNames ...string)`: Sets the order in which the `EndBlock()` function of each module will be called at the end of each block. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). - `RegisterInvariants(ir sdk.InvariantRegistry)`: Registers the [invariants](./invariants.md) of each module. - `RegisterRoutes(router sdk.Router, queryRouter sdk.QueryRouter, legacyQuerierCdc *codec.LegacyAmino)`: Registers legacy [`Msg`](./messages-and-queries.md#messages) and [`querier`](./query-services.md#legacy-queriers) routes. - `RegisterServices(cfg Configurator)`: Registers all module services. diff --git a/docs/run-node/interact-node.md b/docs/run-node/interact-node.md index a07981341fe7..bb208f7d8df1 100644 --- a/docs/run-node/interact-node.md +++ b/docs/run-node/interact-node.md @@ -16,7 +16,7 @@ There are multiple ways to interact with a node: using the CLI, using gRPC or us Now that your chain is running, it is time to try sending tokens from the first account you created to a second account. In a new terminal window, start by running the following query command: ```bash -simd query account $MY_VALIDATOR_ADDRESS --chain-id my-test-chain +simd query bank balances $MY_VALIDATOR_ADDRESS --chain-id my-test-chain ``` You should see the current balance of the account you created, equal to the original balance of `stake` you granted it minus the amount you delegated via the `gentx`. Now, create a second account: @@ -31,16 +31,16 @@ RECIPIENT=$(simd keys show recipient -a --keyring-backend test) The command above creates a local key-pair that is not yet registered on the chain. An account is created the first time it receives tokens from another account. Now, run the following command to send tokens to the `recipient` account: ```bash -simd tx bank send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000stake --chain-id my-test-chain +simd tx bank send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000000stake --chain-id my-test-chain --keyring-backend test # Check that the recipient account did receive the tokens. -simd query account $RECIPIENT --chain-id my-test-chain +simd query bank balances $RECIPIENT --chain-id my-test-chain ``` Finally, delegate some of the stake tokens sent to the `recipient` account to the validator: ```bash -simd tx staking delegate $(simd keys show my_validator --bech val -a --keyring-backend test) 500stake --from recipient --chain-id my-test-chain +simd tx staking delegate $(simd keys show my_validator --bech val -a --keyring-backend test) 500stake --from recipient --chain-id my-test-chain --keyring-backend test # Query the total delegations to `validator`. simd query staking delegations-to $(simd keys show my_validator --bech val -a --keyring-backend test) --chain-id my-test-chain diff --git a/docs/run-node/run-node.md b/docs/run-node/run-node.md index aee7d84e1301..d7aaf8f5822d 100644 --- a/docs/run-node/run-node.md +++ b/docs/run-node/run-node.md @@ -44,7 +44,7 @@ Before starting the chain, you need to populate the state with at least one acco Now that you have created a local account, go ahead and grant it some `stake` tokens in your chain's genesis file. Doing so will also make sure your chain is aware of this account's existence: ```bash -simd add-genesis-account $MY_VALIDATOR_ADDRESS 100000000stake +simd add-genesis-account $MY_VALIDATOR_ADDRESS 100000000000stake ``` Recall that `$MY_VALIDATOR_ADDRESS` is a variable that holds the address of the `my_validator` key in the [keyring](./keyring.md#adding-keys-to-the-keyring). Also note that the tokens in the SDK have the `{amount}{denom}` format: `amount` is is a 18-digit-precision decimal number, and `denom` is the unique token identifier with its denomination key (e.g. `atom` or `uatom`). Here, we are granting `stake` tokens, as `stake` is the token identifier used for staking in [`simapp`](https://github.com/cosmos/cosmos-sdk/tree/v0.40.0-rc3/simapp). For your own chain with its own staking denom, that token identifier should be used instead. @@ -53,7 +53,7 @@ Now that your account has some tokens, you need to add a validator to your chain ```bash # Create a gentx. -simd gentx my_validator 100000stake --chain-id my-test-chain --keyring-backend test +simd gentx my_validator 100000000stake --chain-id my-test-chain --keyring-backend test # Add the gentx to the genesis file. simd collect-gentxs diff --git a/docs/run-node/txs.md b/docs/run-node/txs.md index 9fbc642efc9d..ce977212d232 100644 --- a/docs/run-node/txs.md +++ b/docs/run-node/txs.md @@ -11,7 +11,7 @@ This document describes how to generate an (unsigned) transaction, signing it (w The easiest way to send transactions is using the CLI, as we have seen in the previous page when [interacting with a node](./interact-node.md#using-the-cli). For example, running the following command ```bash -simd tx bank send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000stake --chain-id my-test-chain +simd tx bank send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000stake --chain-id my-test-chain --keyring-backend test ``` will run the following steps: From c252a60ff8781a01c716aba8fa661954d6e6c703 Mon Sep 17 00:00:00 2001 From: Artur Troian Date: Thu, 28 Jan 2021 20:58:44 -0500 Subject: [PATCH 085/152] fix: bind values from env variables to flags (#8337) allows clients access values in env variables Signed-off-by: Artur Troian --- docs/core/cli.md | 18 ++++++++++++++++++ server/util.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/docs/core/cli.md b/docs/core/cli.md index 8e11bf488d2b..10203e769e8c 100644 --- a/docs/core/cli.md +++ b/docs/core/cli.md @@ -108,6 +108,24 @@ Flags are added to commands directly (generally in the [module's CLI file](../bu +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/simapp/simd/cmd/root.go#L118 +## Environment variables + +Each flag is bound to it's respecteve named environment variable. Then name of the environment variable consist of two parts - capital case `basename` followed by flag name of the flag. `-` must be substituted with `_`. For example flag `--home` for application with basename `GAIA` is bound to `GAIA_HOME`. It allows to reduce amount of flags typed for routine operations. For example instead of: +```sh +gaia --home=./ --node= --chain-id="testchain-1" --keyring-backend=test tx ... --from= +``` +this will be more convinient: +```sh +# define env variables in .env, .envrc etc +GAIA_HOME= +GAIA_NODE= +GAIA_CHAIN_ID="testchain-1" +GAIA_KEYRING_BACKEND="test" + +# and later just use +gaia tx ... --from= +``` + ## Configurations It is vital that the root command of an application uses `PersistentPreRun()` cobra command property for executing the command, so all child commands have access to the server and client contexts. These contexts are set as their default values initially and maybe modified, scoped to the command, in their respective `PersistentPreRun()` functions. Note that the `client.Context` is typically pre-populated with "default" values that may be useful for all commands to inherit and override if necessary. diff --git a/server/util.go b/server/util.go index e461a12fb843..b431b715db27 100644 --- a/server/util.go +++ b/server/util.go @@ -17,6 +17,7 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/spf13/cobra" + "github.com/spf13/pflag" "github.com/spf13/viper" tmcfg "github.com/tendermint/tendermint/config" tmlog "github.com/tendermint/tendermint/libs/log" @@ -63,6 +64,37 @@ func NewContext(v *viper.Viper, config *tmcfg.Config, logger tmlog.Logger) *Cont return &Context{v, config, logger} } +func bindFlags(basename string, cmd *cobra.Command, v *viper.Viper) (err error) { + defer func() { + recover() + }() + + cmd.Flags().VisitAll(func(f *pflag.Flag) { + // Environment variables can't have dashes in them, so bind them to their equivalent + // keys with underscores, e.g. --favorite-color to STING_FAVORITE_COLOR + err = v.BindEnv(f.Name, fmt.Sprintf("%s_%s", basename, strings.ToUpper(strings.ReplaceAll(f.Name, "-", "_")))) + if err != nil { + panic(err) + } + + err = v.BindPFlag(f.Name, f) + if err != nil { + panic(err) + } + + // Apply the viper config value to the flag when the flag is not set and viper has a value + if !f.Changed && v.IsSet(f.Name) { + val := v.Get(f.Name) + err = cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val)) + if err != nil { + panic(err) + } + } + }) + + return +} + // InterceptConfigsPreRunHandler performs a pre-run function for the root daemon // application command. It will create a Viper literal and a default server // Context. The server Tendermint configuration will either be read and parsed @@ -98,6 +130,9 @@ func InterceptConfigsPreRunHandler(cmd *cobra.Command) error { // return value is a tendermint configuration object serverCtx.Config = config + if err = bindFlags(basename, cmd, serverCtx.Viper); err != nil { + return err + } var logWriter io.Writer if strings.ToLower(serverCtx.Viper.GetString(flags.FlagLogFormat)) == tmcfg.LogFormatPlain { From 3b8e0f9387386dc3cb375a662bc4bc0ad211f284 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 29 Jan 2021 18:46:23 +0000 Subject: [PATCH 086/152] store/multistore: revert a height limit increase from #8396 (#8466) See https://github.com/cosmos/cosmos-sdk/pull/8396#discussion_r565654207 Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- store/rootmulti/store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index 0e8cba44ef5e..1ca43eae9d4e 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -711,7 +711,7 @@ func (rs *Store) Restore( if height == 0 { return sdkerrors.Wrap(sdkerrors.ErrLogic, "cannot restore snapshot at height 0") } - if height > uint64(math.MaxUint64) { + if height > uint64(math.MaxInt64) { return sdkerrors.Wrapf(snapshottypes.ErrInvalidMetadata, "snapshot height %v cannot exceed %v", height, int64(math.MaxInt64)) } From d97e7907f176777ed8a464006d360bb3e1a223e4 Mon Sep 17 00:00:00 2001 From: atheeshp <59333759+atheeshp@users.noreply.github.com> Date: Sat, 30 Jan 2021 01:24:51 +0530 Subject: [PATCH 087/152] Add fee grant module (#8061) * Add docs * Add BasicFeeAllowance implementation * Add expiration structs and complete basic fee * Add delegation messages, add validation logic * Add keeper and helper structs * Add alias and handler to top level * Add delegation module * Add basic querier * Add types tests * Add types tests * More internal test coverage * Solid internal test coverage * Expose Querier to top level module * Add FeeAccount to auth/types, like StdTx, SignDoc * Fix all tests in x/auth * All tests pass * Appease the Golang Linter * Add fee-account command line flag * Start on DelegatedDeductFeeDecorator * Cleanup the Decorator * Wire up delegation module in simapp * add basic test for decorator (no delegation) * Table tests for deduct fees * Table tests over all conditions of delegated fee decorator * Build full ante handler stack and test it * Start genesis * Implement Genesis * Rename package delegation to subkeys * Clarify antes test cases, handle empty account w/o fees * Allow paying delegated fees with no account * Pull mempool into delegated ante, for control on StdFee * Use custom DelegatedTx, DelegatedFee for subkeys * Revert all changes to x/auth.StdTx * Appease scopelint * Register DelegatedTx with codec * Address PR comments * Remove unnecessary DelegatedMempoolFeeDecorator * Cleaned up errors in querier * Clean up message sign bytes * Minor PR comments * Replace GetAllFees... with Iterator variants * PrepareForExport adjusts grant expiration height * Panic on de/serialization error in keeper * Move custom ante handler chain to tests, update docs * More cleanup * More doc cleanup * Renamed subkeys module to fee_grant * Rename subkeys/delegation to fee grant in all strings * Modify Msg and Keeper methods to use Grant not Delegate * Add PeriodicFeeAllowance * Update aliases * Cover all accept cases for PeriodicFeeAllowance * Et tu scopelint? * Update docs as requested * Remove error return from GetFeeGrant * Code cleanup as requested by PR * Updated all errors to use new sdk/errors package * Use test suite for keeper tests * Clean up alias.go file * Define expected interfaces in exported, rather than importing from account * Remove dependency on auth/ante * Improve godoc, Logger * Cleaned up ExpiresAt * Improve error reporting with UseGrantedFee * Enforce period limit subset of basic limit * Add events * Rename fee_grant to feegrant * Ensure KeeperTestSuite actually runs * Move types/tx to types * Update alias file, include ante * I do need nolint in alias.go * Properly emit events in the handler. Use cosmos-sdk in amino types * Update godoc * Linting... * Update errors * Update pkg doc and fix ante-handler order * Merge PR #5782: Migrate x/feegrant to proto * fix errors * proto changes * proto changes * fix errors * fix errors * genesis state changed to proto * fix keeper tests * fix test * fixed tests * fix tests * updated expected keepers * updated ante tests * lint * deleted alias.go * tx updated to proto tx * remove explicit signmode * tests * Added `cli/query.go` * Added tx.go in cli * updated `module.go` * resolve errors in tx.go * Add fee payer gentx func * updated tx * fixed error * WIP: cli tests * fix query error * fix tests * Unused types and funcs * fix tests * rename helper func to create tx * remove unused * update tx cfg * fix cli tests * added simulations * Add `decoder.go` * fix build fail * added init genesis code * update tx.go * fixed LGTM alert * modified cli * remove gogoproto extensions * change acc address type to string * lint * fix simulations * Add gen simulations * remove legacy querier * remove legacy code * add grpc queries tests * fix simulations * update module.go * lint * register feegrant NewSimulationManager * fix sims * fix sims * add genesis test * add periodic grant * updated cmd * changed times * updated flags * removed days as period clock * added condition for period and exp * add periodic fee cli tests * udpated tests * fix lint * fix tests * fix sims * renaming to `fee_grant` * review changes * fix test * add condition for duplicate grants * fix tests * add `genTxWithFeeGranter` in tests * fix simulation * one of changes & test fixes * fix test * fix lint * changed package name `feegrant` to `fee_grant` * review comments * review changes * review change * review changes * added fee-account in flags * address review changes * read fee granter from cli * updated create account with mnemonic * Address review comments * move `simapp/ante` file to `feegrant/ante` * update keeper logic to create account * update docs * fix tests * update `serviceMsgClientConn` from `msgservice` * review changes * add test case for using more fees than allowed * eliminate panic checks from keeper * fix lint * change store keys string to bytes * fix tests * review changes * review changes * udpate docs * make spend limit optional * fix tests * fix tests * review changes * add norace tag * proto-docs * add docs Co-authored-by: Ethan Frey Co-authored-by: Alexander Bezobchuk Co-authored-by: Aleksandr Bezobchuk Co-authored-by: SaReN Co-authored-by: aleem1413 Co-authored-by: MD Aleem <72057206+aleem1314@users.noreply.github.com> Co-authored-by: Anil Kumar Kammari Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- client/cmd.go | 13 + client/context.go | 8 + client/flags/flags.go | 2 + client/query.go | 5 + client/tx/tx.go | 1 + client/tx_config.go | 1 + docs/core/proto-docs.md | 7596 +++++++++--------- proto/cosmos/feegrant/v1beta1/feegrant.proto | 81 + proto/cosmos/feegrant/v1beta1/genesis.proto | 12 + proto/cosmos/feegrant/v1beta1/query.proto | 52 + proto/cosmos/feegrant/v1beta1/tx.proto | 40 + simapp/app.go | 17 +- simapp/params/weights.go | 4 + x/auth/legacy/legacytx/stdtx_builder.go | 3 + x/feegrant/ante/ante.go | 35 + x/feegrant/ante/fee.go | 82 + x/feegrant/ante/fee_test.go | 287 + x/feegrant/client/cli/cli_test.go | 621 ++ x/feegrant/client/cli/query.go | 129 + x/feegrant/client/cli/tx.go | 211 + x/feegrant/client/rest/grpc_query_test.go | 209 + x/feegrant/doc.go | 29 + x/feegrant/genesis.go | 61 + x/feegrant/genesis_test.go | 56 + x/feegrant/keeper/grpc_query.go | 94 + x/feegrant/keeper/keeper.go | 190 + x/feegrant/keeper/keeper_test.go | 257 + x/feegrant/keeper/msg_server.go | 72 + x/feegrant/module.go | 210 + x/feegrant/simulation/decoder.go | 26 + x/feegrant/simulation/decoder_test.go | 62 + x/feegrant/simulation/genesis.go | 38 + x/feegrant/simulation/genesis_test.go | 39 + x/feegrant/simulation/operations.go | 200 + x/feegrant/simulation/operations_test.go | 173 + x/feegrant/types/basic_fee.go | 61 + x/feegrant/types/basic_fee_test.go | 140 + x/feegrant/types/codec.go | 24 + x/feegrant/types/errors.go | 21 + x/feegrant/types/events.go | 13 + x/feegrant/types/expected_keepers.go | 23 + x/feegrant/types/expiration.go | 138 + x/feegrant/types/expiration_test.go | 161 + x/feegrant/types/feegrant.pb.go | 1701 ++++ x/feegrant/types/fees.go | 32 + x/feegrant/types/genesis.go | 40 + x/feegrant/types/genesis.pb.go | 333 + x/feegrant/types/grant.go | 92 + x/feegrant/types/grant_test.go | 99 + x/feegrant/types/key.go | 35 + x/feegrant/types/msgs.go | 101 + x/feegrant/types/periodic_fee.go | 120 + x/feegrant/types/periodic_fee_test.go | 205 + x/feegrant/types/query.pb.go | 1172 +++ x/feegrant/types/query.pb.gw.go | 322 + x/feegrant/types/tx.pb.go | 1033 +++ x/mint/simulation/decoder.go | 2 +- 57 files changed, 13148 insertions(+), 3636 deletions(-) create mode 100644 proto/cosmos/feegrant/v1beta1/feegrant.proto create mode 100644 proto/cosmos/feegrant/v1beta1/genesis.proto create mode 100644 proto/cosmos/feegrant/v1beta1/query.proto create mode 100644 proto/cosmos/feegrant/v1beta1/tx.proto create mode 100644 x/feegrant/ante/ante.go create mode 100644 x/feegrant/ante/fee.go create mode 100644 x/feegrant/ante/fee_test.go create mode 100644 x/feegrant/client/cli/cli_test.go create mode 100644 x/feegrant/client/cli/query.go create mode 100644 x/feegrant/client/cli/tx.go create mode 100644 x/feegrant/client/rest/grpc_query_test.go create mode 100644 x/feegrant/doc.go create mode 100644 x/feegrant/genesis.go create mode 100644 x/feegrant/genesis_test.go create mode 100644 x/feegrant/keeper/grpc_query.go create mode 100644 x/feegrant/keeper/keeper.go create mode 100644 x/feegrant/keeper/keeper_test.go create mode 100644 x/feegrant/keeper/msg_server.go create mode 100644 x/feegrant/module.go create mode 100644 x/feegrant/simulation/decoder.go create mode 100644 x/feegrant/simulation/decoder_test.go create mode 100644 x/feegrant/simulation/genesis.go create mode 100644 x/feegrant/simulation/genesis_test.go create mode 100644 x/feegrant/simulation/operations.go create mode 100644 x/feegrant/simulation/operations_test.go create mode 100644 x/feegrant/types/basic_fee.go create mode 100644 x/feegrant/types/basic_fee_test.go create mode 100644 x/feegrant/types/codec.go create mode 100644 x/feegrant/types/errors.go create mode 100644 x/feegrant/types/events.go create mode 100644 x/feegrant/types/expected_keepers.go create mode 100644 x/feegrant/types/expiration.go create mode 100644 x/feegrant/types/expiration_test.go create mode 100644 x/feegrant/types/feegrant.pb.go create mode 100644 x/feegrant/types/fees.go create mode 100644 x/feegrant/types/genesis.go create mode 100644 x/feegrant/types/genesis.pb.go create mode 100644 x/feegrant/types/grant.go create mode 100644 x/feegrant/types/grant_test.go create mode 100644 x/feegrant/types/key.go create mode 100644 x/feegrant/types/msgs.go create mode 100644 x/feegrant/types/periodic_fee.go create mode 100644 x/feegrant/types/periodic_fee_test.go create mode 100644 x/feegrant/types/query.pb.go create mode 100644 x/feegrant/types/query.pb.gw.go create mode 100644 x/feegrant/types/tx.pb.go diff --git a/client/cmd.go b/client/cmd.go index eccf59c3515c..437022695d47 100644 --- a/client/cmd.go +++ b/client/cmd.go @@ -221,6 +221,19 @@ func readTxCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Context, err clientCtx = clientCtx.WithSignModeStr(signModeStr) } + if clientCtx.FeeGranter == nil || flagSet.Changed(flags.FlagFeeAccount) { + granter, _ := flagSet.GetString(flags.FlagFeeAccount) + + if granter != "" { + granterAcc, err := sdk.AccAddressFromBech32(granter) + if err != nil { + return clientCtx, err + } + + clientCtx = clientCtx.WithFeeGranterAddress(granterAcc) + } + } + if clientCtx.From == "" || flagSet.Changed(flags.FlagFrom) { from, _ := flagSet.GetString(flags.FlagFrom) fromAddr, fromName, keyType, err := GetFromFields(clientCtx.Keyring, from, clientCtx.GenerateOnly) diff --git a/client/context.go b/client/context.go index 0e3d1181af6e..f7f555339c2c 100644 --- a/client/context.go +++ b/client/context.go @@ -44,6 +44,7 @@ type Context struct { TxConfig TxConfig AccountRetriever AccountRetriever NodeURI string + FeeGranter sdk.AccAddress // TODO: Deprecated (remove). LegacyAmino *codec.LegacyAmino @@ -166,6 +167,13 @@ func (ctx Context) WithFromAddress(addr sdk.AccAddress) Context { return ctx } +// WithFeeGranterAddress returns a copy of the context with an updated fee granter account +// address. +func (ctx Context) WithFeeGranterAddress(addr sdk.AccAddress) Context { + ctx.FeeGranter = addr + return ctx +} + // WithBroadcastMode returns a copy of the context with an updated broadcast // mode. func (ctx Context) WithBroadcastMode(mode string) Context { diff --git a/client/flags/flags.go b/client/flags/flags.go index 282a61c4c9fb..1afb55b46733 100644 --- a/client/flags/flags.go +++ b/client/flags/flags.go @@ -70,6 +70,7 @@ const ( FlagCountTotal = "count-total" FlagTimeoutHeight = "timeout-height" FlagKeyAlgorithm = "algo" + FlagFeeAccount = "fee-account" // Tendermint logging flags FlagLogLevel = "log_level" @@ -112,6 +113,7 @@ func AddTxFlagsToCmd(cmd *cobra.Command) { cmd.Flags().String(FlagKeyringBackend, DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)") cmd.Flags().String(FlagSignMode, "", "Choose sign mode (direct|amino-json), this is an advanced feature") cmd.Flags().Uint64(FlagTimeoutHeight, 0, "Set a block timeout height to prevent the tx from being committed past a certain height") + cmd.Flags().String(FlagFeeAccount, "", "Fee account pays fees for the transaction instead of deducting from the signer") // --gas can accept integers and "auto" cmd.Flags().String(FlagGas, "", fmt.Sprintf("gas limit to set per-transaction; set to %q to calculate sufficient gas automatically (default %d)", GasFlagAuto, DefaultGasLimit)) diff --git a/client/query.go b/client/query.go index 18a5c3c2f4ee..bb65d9bf3833 100644 --- a/client/query.go +++ b/client/query.go @@ -57,6 +57,11 @@ func (ctx Context) GetFromAddress() sdk.AccAddress { return ctx.FromAddress } +// GetFeeGranterAddress returns the fee granter address from the context +func (ctx Context) GetFeeGranterAddress() sdk.AccAddress { + return ctx.FeeGranter +} + // GetFromName returns the key name for the current context. func (ctx Context) GetFromName() string { return ctx.FromName diff --git a/client/tx/tx.go b/client/tx/tx.go index 594293732bc8..62e3e9098eea 100644 --- a/client/tx/tx.go +++ b/client/tx/tx.go @@ -117,6 +117,7 @@ func BroadcastTx(clientCtx client.Context, txf Factory, msgs ...sdk.Msg) error { } } + tx.SetFeeGranter(clientCtx.GetFeeGranterAddress()) err = Sign(txf, clientCtx.GetFromName(), tx, true) if err != nil { return err diff --git a/client/tx_config.go b/client/tx_config.go index 6992a7a2402d..8220e917b2bb 100644 --- a/client/tx_config.go +++ b/client/tx_config.go @@ -42,5 +42,6 @@ type ( SetFeeAmount(amount sdk.Coins) SetGasLimit(limit uint64) SetTimeoutHeight(height uint64) + SetFeeGranter(feeGranter sdk.AccAddress) } ) diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index ec30ba730ba1..6b5909a3dbc3 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -4,70 +4,116 @@ ## Table of Contents -- [cosmos/auth/v1beta1/auth.proto](#cosmos/auth/v1beta1/auth.proto) - - [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) - - [ModuleAccount](#cosmos.auth.v1beta1.ModuleAccount) - - [Params](#cosmos.auth.v1beta1.Params) +- [cosmos/tx/v1beta1/tx.proto](#cosmos/tx/v1beta1/tx.proto) + - [AuthInfo](#cosmos.tx.v1beta1.AuthInfo) + - [Fee](#cosmos.tx.v1beta1.Fee) + - [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) + - [ModeInfo.Multi](#cosmos.tx.v1beta1.ModeInfo.Multi) + - [ModeInfo.Single](#cosmos.tx.v1beta1.ModeInfo.Single) + - [SignDoc](#cosmos.tx.v1beta1.SignDoc) + - [SignerInfo](#cosmos.tx.v1beta1.SignerInfo) + - [Tx](#cosmos.tx.v1beta1.Tx) + - [TxBody](#cosmos.tx.v1beta1.TxBody) + - [TxRaw](#cosmos.tx.v1beta1.TxRaw) -- [cosmos/auth/v1beta1/genesis.proto](#cosmos/auth/v1beta1/genesis.proto) - - [GenesisState](#cosmos.auth.v1beta1.GenesisState) +- [cosmos/tx/v1beta1/service.proto](#cosmos/tx/v1beta1/service.proto) + - [BroadcastTxRequest](#cosmos.tx.v1beta1.BroadcastTxRequest) + - [BroadcastTxResponse](#cosmos.tx.v1beta1.BroadcastTxResponse) + - [GetTxRequest](#cosmos.tx.v1beta1.GetTxRequest) + - [GetTxResponse](#cosmos.tx.v1beta1.GetTxResponse) + - [GetTxsEventRequest](#cosmos.tx.v1beta1.GetTxsEventRequest) + - [GetTxsEventResponse](#cosmos.tx.v1beta1.GetTxsEventResponse) + - [SimulateRequest](#cosmos.tx.v1beta1.SimulateRequest) + - [SimulateResponse](#cosmos.tx.v1beta1.SimulateResponse) -- [cosmos/auth/v1beta1/query.proto](#cosmos/auth/v1beta1/query.proto) - - [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) - - [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) - - [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) + - [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) - - [Query](#cosmos.auth.v1beta1.Query) + - [Service](#cosmos.tx.v1beta1.Service) -- [cosmos/base/v1beta1/coin.proto](#cosmos/base/v1beta1/coin.proto) - - [Coin](#cosmos.base.v1beta1.Coin) - - [DecCoin](#cosmos.base.v1beta1.DecCoin) - - [DecProto](#cosmos.base.v1beta1.DecProto) - - [IntProto](#cosmos.base.v1beta1.IntProto) +- [cosmos/tx/signing/v1beta1/signing.proto](#cosmos/tx/signing/v1beta1/signing.proto) + - [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) + - [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) + - [SignatureDescriptor.Data.Multi](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Multi) + - [SignatureDescriptor.Data.Single](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Single) + - [SignatureDescriptors](#cosmos.tx.signing.v1beta1.SignatureDescriptors) -- [cosmos/authz/v1beta1/authz.proto](#cosmos/authz/v1beta1/authz.proto) - - [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) - - [GenericAuthorization](#cosmos.authz.v1beta1.GenericAuthorization) - - [SendAuthorization](#cosmos.authz.v1beta1.SendAuthorization) + - [SignMode](#cosmos.tx.signing.v1beta1.SignMode) -- [cosmos/base/abci/v1beta1/abci.proto](#cosmos/base/abci/v1beta1/abci.proto) - - [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) - - [Attribute](#cosmos.base.abci.v1beta1.Attribute) - - [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) - - [MsgData](#cosmos.base.abci.v1beta1.MsgData) - - [Result](#cosmos.base.abci.v1beta1.Result) - - [SearchTxsResult](#cosmos.base.abci.v1beta1.SearchTxsResult) - - [SimulationResponse](#cosmos.base.abci.v1beta1.SimulationResponse) - - [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) - - [TxMsgData](#cosmos.base.abci.v1beta1.TxMsgData) - - [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) +- [cosmos/crisis/v1beta1/tx.proto](#cosmos/crisis/v1beta1/tx.proto) + - [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) + - [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) -- [cosmos/authz/v1beta1/tx.proto](#cosmos/authz/v1beta1/tx.proto) - - [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) - - [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) - - [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) - - [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) - - [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) - - [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) + - [Msg](#cosmos.crisis.v1beta1.Msg) - - [Msg](#cosmos.authz.v1beta1.Msg) +- [cosmos/crisis/v1beta1/genesis.proto](#cosmos/crisis/v1beta1/genesis.proto) + - [GenesisState](#cosmos.crisis.v1beta1.GenesisState) -- [cosmos/authz/v1beta1/genesis.proto](#cosmos/authz/v1beta1/genesis.proto) - - [GenesisState](#cosmos.authz.v1beta1.GenesisState) - - [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) +- [cosmos/crypto/multisig/keys.proto](#cosmos/crypto/multisig/keys.proto) + - [LegacyAminoPubKey](#cosmos.crypto.multisig.LegacyAminoPubKey) -- [cosmos/base/query/v1beta1/pagination.proto](#cosmos/base/query/v1beta1/pagination.proto) - - [PageRequest](#cosmos.base.query.v1beta1.PageRequest) - - [PageResponse](#cosmos.base.query.v1beta1.PageResponse) +- [cosmos/crypto/multisig/v1beta1/multisig.proto](#cosmos/crypto/multisig/v1beta1/multisig.proto) + - [CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) + - [MultiSignature](#cosmos.crypto.multisig.v1beta1.MultiSignature) -- [cosmos/authz/v1beta1/query.proto](#cosmos/authz/v1beta1/query.proto) - - [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) - - [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) - - [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) - - [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) +- [cosmos/crypto/secp256k1/keys.proto](#cosmos/crypto/secp256k1/keys.proto) + - [PrivKey](#cosmos.crypto.secp256k1.PrivKey) + - [PubKey](#cosmos.crypto.secp256k1.PubKey) - - [Query](#cosmos.authz.v1beta1.Query) +- [cosmos/crypto/ed25519/keys.proto](#cosmos/crypto/ed25519/keys.proto) + - [PrivKey](#cosmos.crypto.ed25519.PrivKey) + - [PubKey](#cosmos.crypto.ed25519.PubKey) + +- [cosmos/mint/v1beta1/query.proto](#cosmos/mint/v1beta1/query.proto) + - [QueryAnnualProvisionsRequest](#cosmos.mint.v1beta1.QueryAnnualProvisionsRequest) + - [QueryAnnualProvisionsResponse](#cosmos.mint.v1beta1.QueryAnnualProvisionsResponse) + - [QueryInflationRequest](#cosmos.mint.v1beta1.QueryInflationRequest) + - [QueryInflationResponse](#cosmos.mint.v1beta1.QueryInflationResponse) + - [QueryParamsRequest](#cosmos.mint.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.mint.v1beta1.QueryParamsResponse) + + - [Query](#cosmos.mint.v1beta1.Query) + +- [cosmos/mint/v1beta1/genesis.proto](#cosmos/mint/v1beta1/genesis.proto) + - [GenesisState](#cosmos.mint.v1beta1.GenesisState) + +- [cosmos/mint/v1beta1/mint.proto](#cosmos/mint/v1beta1/mint.proto) + - [Minter](#cosmos.mint.v1beta1.Minter) + - [Params](#cosmos.mint.v1beta1.Params) + +- [cosmos/feegrant/v1beta1/feegrant.proto](#cosmos/feegrant/v1beta1/feegrant.proto) + - [BasicFeeAllowance](#cosmos.feegrant.v1beta1.BasicFeeAllowance) + - [Duration](#cosmos.feegrant.v1beta1.Duration) + - [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) + - [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) + - [PeriodicFeeAllowance](#cosmos.feegrant.v1beta1.PeriodicFeeAllowance) + +- [cosmos/feegrant/v1beta1/query.proto](#cosmos/feegrant/v1beta1/query.proto) + - [QueryFeeAllowanceRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowanceRequest) + - [QueryFeeAllowanceResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowanceResponse) + - [QueryFeeAllowancesRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowancesRequest) + - [QueryFeeAllowancesResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowancesResponse) + + - [Query](#cosmos.feegrant.v1beta1.Query) + +- [cosmos/feegrant/v1beta1/tx.proto](#cosmos/feegrant/v1beta1/tx.proto) + - [MsgGrantFeeAllowance](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowance) + - [MsgGrantFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowanceResponse) + - [MsgRevokeFeeAllowance](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowance) + - [MsgRevokeFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowanceResponse) + + - [Msg](#cosmos.feegrant.v1beta1.Msg) + +- [cosmos/feegrant/v1beta1/genesis.proto](#cosmos/feegrant/v1beta1/genesis.proto) + - [GenesisState](#cosmos.feegrant.v1beta1.GenesisState) + +- [cosmos/capability/v1beta1/capability.proto](#cosmos/capability/v1beta1/capability.proto) + - [Capability](#cosmos.capability.v1beta1.Capability) + - [CapabilityOwners](#cosmos.capability.v1beta1.CapabilityOwners) + - [Owner](#cosmos.capability.v1beta1.Owner) + +- [cosmos/capability/v1beta1/genesis.proto](#cosmos/capability/v1beta1/genesis.proto) + - [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) + - [GenesisState](#cosmos.capability.v1beta1.GenesisState) - [cosmos/bank/v1beta1/bank.proto](#cosmos/bank/v1beta1/bank.proto) - [DenomUnit](#cosmos.bank.v1beta1.DenomUnit) @@ -78,10 +124,6 @@ - [SendEnabled](#cosmos.bank.v1beta1.SendEnabled) - [Supply](#cosmos.bank.v1beta1.Supply) -- [cosmos/bank/v1beta1/genesis.proto](#cosmos/bank/v1beta1/genesis.proto) - - [Balance](#cosmos.bank.v1beta1.Balance) - - [GenesisState](#cosmos.bank.v1beta1.GenesisState) - - [cosmos/bank/v1beta1/query.proto](#cosmos/bank/v1beta1/query.proto) - [QueryAllBalancesRequest](#cosmos.bank.v1beta1.QueryAllBalancesRequest) - [QueryAllBalancesResponse](#cosmos.bank.v1beta1.QueryAllBalancesResponse) @@ -108,107 +150,85 @@ - [Msg](#cosmos.bank.v1beta1.Msg) -- [cosmos/base/kv/v1beta1/kv.proto](#cosmos/base/kv/v1beta1/kv.proto) - - [Pair](#cosmos.base.kv.v1beta1.Pair) - - [Pairs](#cosmos.base.kv.v1beta1.Pairs) - -- [cosmos/base/reflection/v1beta1/reflection.proto](#cosmos/base/reflection/v1beta1/reflection.proto) - - [ListAllInterfacesRequest](#cosmos.base.reflection.v1beta1.ListAllInterfacesRequest) - - [ListAllInterfacesResponse](#cosmos.base.reflection.v1beta1.ListAllInterfacesResponse) - - [ListImplementationsRequest](#cosmos.base.reflection.v1beta1.ListImplementationsRequest) - - [ListImplementationsResponse](#cosmos.base.reflection.v1beta1.ListImplementationsResponse) - - - [ReflectionService](#cosmos.base.reflection.v1beta1.ReflectionService) - -- [cosmos/base/snapshots/v1beta1/snapshot.proto](#cosmos/base/snapshots/v1beta1/snapshot.proto) - - [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) - - [Snapshot](#cosmos.base.snapshots.v1beta1.Snapshot) - -- [cosmos/base/store/v1beta1/commit_info.proto](#cosmos/base/store/v1beta1/commit_info.proto) - - [CommitID](#cosmos.base.store.v1beta1.CommitID) - - [CommitInfo](#cosmos.base.store.v1beta1.CommitInfo) - - [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) +- [cosmos/bank/v1beta1/genesis.proto](#cosmos/bank/v1beta1/genesis.proto) + - [Balance](#cosmos.bank.v1beta1.Balance) + - [GenesisState](#cosmos.bank.v1beta1.GenesisState) -- [cosmos/base/store/v1beta1/snapshot.proto](#cosmos/base/store/v1beta1/snapshot.proto) - - [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) - - [SnapshotItem](#cosmos.base.store.v1beta1.SnapshotItem) - - [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) +- [cosmos/authz/v1beta1/authz.proto](#cosmos/authz/v1beta1/authz.proto) + - [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) + - [GenericAuthorization](#cosmos.authz.v1beta1.GenericAuthorization) + - [SendAuthorization](#cosmos.authz.v1beta1.SendAuthorization) -- [cosmos/base/tendermint/v1beta1/query.proto](#cosmos/base/tendermint/v1beta1/query.proto) - - [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) - - [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) - - [GetLatestBlockRequest](#cosmos.base.tendermint.v1beta1.GetLatestBlockRequest) - - [GetLatestBlockResponse](#cosmos.base.tendermint.v1beta1.GetLatestBlockResponse) - - [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) - - [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) - - [GetNodeInfoRequest](#cosmos.base.tendermint.v1beta1.GetNodeInfoRequest) - - [GetNodeInfoResponse](#cosmos.base.tendermint.v1beta1.GetNodeInfoResponse) - - [GetSyncingRequest](#cosmos.base.tendermint.v1beta1.GetSyncingRequest) - - [GetSyncingResponse](#cosmos.base.tendermint.v1beta1.GetSyncingResponse) - - [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) - - [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) - - [Module](#cosmos.base.tendermint.v1beta1.Module) - - [Validator](#cosmos.base.tendermint.v1beta1.Validator) - - [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) +- [cosmos/authz/v1beta1/query.proto](#cosmos/authz/v1beta1/query.proto) + - [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) + - [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) + - [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) + - [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) - - [Service](#cosmos.base.tendermint.v1beta1.Service) + - [Query](#cosmos.authz.v1beta1.Query) -- [cosmos/capability/v1beta1/capability.proto](#cosmos/capability/v1beta1/capability.proto) - - [Capability](#cosmos.capability.v1beta1.Capability) - - [CapabilityOwners](#cosmos.capability.v1beta1.CapabilityOwners) - - [Owner](#cosmos.capability.v1beta1.Owner) +- [cosmos/authz/v1beta1/tx.proto](#cosmos/authz/v1beta1/tx.proto) + - [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) + - [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) + - [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) + - [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) + - [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) + - [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) -- [cosmos/capability/v1beta1/genesis.proto](#cosmos/capability/v1beta1/genesis.proto) - - [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) - - [GenesisState](#cosmos.capability.v1beta1.GenesisState) + - [Msg](#cosmos.authz.v1beta1.Msg) -- [cosmos/crisis/v1beta1/genesis.proto](#cosmos/crisis/v1beta1/genesis.proto) - - [GenesisState](#cosmos.crisis.v1beta1.GenesisState) +- [cosmos/authz/v1beta1/genesis.proto](#cosmos/authz/v1beta1/genesis.proto) + - [GenesisState](#cosmos.authz.v1beta1.GenesisState) + - [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) -- [cosmos/crisis/v1beta1/tx.proto](#cosmos/crisis/v1beta1/tx.proto) - - [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) - - [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) +- [cosmos/gov/v1beta1/gov.proto](#cosmos/gov/v1beta1/gov.proto) + - [Deposit](#cosmos.gov.v1beta1.Deposit) + - [DepositParams](#cosmos.gov.v1beta1.DepositParams) + - [Proposal](#cosmos.gov.v1beta1.Proposal) + - [TallyParams](#cosmos.gov.v1beta1.TallyParams) + - [TallyResult](#cosmos.gov.v1beta1.TallyResult) + - [TextProposal](#cosmos.gov.v1beta1.TextProposal) + - [Vote](#cosmos.gov.v1beta1.Vote) + - [VotingParams](#cosmos.gov.v1beta1.VotingParams) - - [Msg](#cosmos.crisis.v1beta1.Msg) + - [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) + - [VoteOption](#cosmos.gov.v1beta1.VoteOption) -- [cosmos/crypto/ed25519/keys.proto](#cosmos/crypto/ed25519/keys.proto) - - [PrivKey](#cosmos.crypto.ed25519.PrivKey) - - [PubKey](#cosmos.crypto.ed25519.PubKey) +- [cosmos/gov/v1beta1/query.proto](#cosmos/gov/v1beta1/query.proto) + - [QueryDepositRequest](#cosmos.gov.v1beta1.QueryDepositRequest) + - [QueryDepositResponse](#cosmos.gov.v1beta1.QueryDepositResponse) + - [QueryDepositsRequest](#cosmos.gov.v1beta1.QueryDepositsRequest) + - [QueryDepositsResponse](#cosmos.gov.v1beta1.QueryDepositsResponse) + - [QueryParamsRequest](#cosmos.gov.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.gov.v1beta1.QueryParamsResponse) + - [QueryProposalRequest](#cosmos.gov.v1beta1.QueryProposalRequest) + - [QueryProposalResponse](#cosmos.gov.v1beta1.QueryProposalResponse) + - [QueryProposalsRequest](#cosmos.gov.v1beta1.QueryProposalsRequest) + - [QueryProposalsResponse](#cosmos.gov.v1beta1.QueryProposalsResponse) + - [QueryTallyResultRequest](#cosmos.gov.v1beta1.QueryTallyResultRequest) + - [QueryTallyResultResponse](#cosmos.gov.v1beta1.QueryTallyResultResponse) + - [QueryVoteRequest](#cosmos.gov.v1beta1.QueryVoteRequest) + - [QueryVoteResponse](#cosmos.gov.v1beta1.QueryVoteResponse) + - [QueryVotesRequest](#cosmos.gov.v1beta1.QueryVotesRequest) + - [QueryVotesResponse](#cosmos.gov.v1beta1.QueryVotesResponse) -- [cosmos/crypto/multisig/keys.proto](#cosmos/crypto/multisig/keys.proto) - - [LegacyAminoPubKey](#cosmos.crypto.multisig.LegacyAminoPubKey) + - [Query](#cosmos.gov.v1beta1.Query) -- [cosmos/crypto/multisig/v1beta1/multisig.proto](#cosmos/crypto/multisig/v1beta1/multisig.proto) - - [CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) - - [MultiSignature](#cosmos.crypto.multisig.v1beta1.MultiSignature) +- [cosmos/gov/v1beta1/tx.proto](#cosmos/gov/v1beta1/tx.proto) + - [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) + - [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) + - [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) + - [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) + - [MsgVote](#cosmos.gov.v1beta1.MsgVote) + - [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) -- [cosmos/crypto/secp256k1/keys.proto](#cosmos/crypto/secp256k1/keys.proto) - - [PrivKey](#cosmos.crypto.secp256k1.PrivKey) - - [PubKey](#cosmos.crypto.secp256k1.PubKey) + - [Msg](#cosmos.gov.v1beta1.Msg) -- [cosmos/distribution/v1beta1/distribution.proto](#cosmos/distribution/v1beta1/distribution.proto) - - [CommunityPoolSpendProposal](#cosmos.distribution.v1beta1.CommunityPoolSpendProposal) - - [CommunityPoolSpendProposalWithDeposit](#cosmos.distribution.v1beta1.CommunityPoolSpendProposalWithDeposit) - - [DelegationDelegatorReward](#cosmos.distribution.v1beta1.DelegationDelegatorReward) - - [DelegatorStartingInfo](#cosmos.distribution.v1beta1.DelegatorStartingInfo) - - [FeePool](#cosmos.distribution.v1beta1.FeePool) - - [Params](#cosmos.distribution.v1beta1.Params) - - [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) - - [ValidatorCurrentRewards](#cosmos.distribution.v1beta1.ValidatorCurrentRewards) - - [ValidatorHistoricalRewards](#cosmos.distribution.v1beta1.ValidatorHistoricalRewards) - - [ValidatorOutstandingRewards](#cosmos.distribution.v1beta1.ValidatorOutstandingRewards) - - [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) - - [ValidatorSlashEvents](#cosmos.distribution.v1beta1.ValidatorSlashEvents) +- [cosmos/gov/v1beta1/genesis.proto](#cosmos/gov/v1beta1/genesis.proto) + - [GenesisState](#cosmos.gov.v1beta1.GenesisState) -- [cosmos/distribution/v1beta1/genesis.proto](#cosmos/distribution/v1beta1/genesis.proto) - - [DelegatorStartingInfoRecord](#cosmos.distribution.v1beta1.DelegatorStartingInfoRecord) - - [DelegatorWithdrawInfo](#cosmos.distribution.v1beta1.DelegatorWithdrawInfo) - - [GenesisState](#cosmos.distribution.v1beta1.GenesisState) - - [ValidatorAccumulatedCommissionRecord](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommissionRecord) - - [ValidatorCurrentRewardsRecord](#cosmos.distribution.v1beta1.ValidatorCurrentRewardsRecord) - - [ValidatorHistoricalRewardsRecord](#cosmos.distribution.v1beta1.ValidatorHistoricalRewardsRecord) - - [ValidatorOutstandingRewardsRecord](#cosmos.distribution.v1beta1.ValidatorOutstandingRewardsRecord) - - [ValidatorSlashEventRecord](#cosmos.distribution.v1beta1.ValidatorSlashEventRecord) +- [cosmos/genutil/v1beta1/genesis.proto](#cosmos/genutil/v1beta1/genesis.proto) + - [GenesisState](#cosmos.genutil.v1beta1.GenesisState) - [cosmos/distribution/v1beta1/query.proto](#cosmos/distribution/v1beta1/query.proto) - [QueryCommunityPoolRequest](#cosmos.distribution.v1beta1.QueryCommunityPoolRequest) @@ -244,112 +264,116 @@ - [Msg](#cosmos.distribution.v1beta1.Msg) -- [cosmos/evidence/v1beta1/evidence.proto](#cosmos/evidence/v1beta1/evidence.proto) - - [Equivocation](#cosmos.evidence.v1beta1.Equivocation) - -- [cosmos/evidence/v1beta1/genesis.proto](#cosmos/evidence/v1beta1/genesis.proto) - - [GenesisState](#cosmos.evidence.v1beta1.GenesisState) - -- [cosmos/evidence/v1beta1/query.proto](#cosmos/evidence/v1beta1/query.proto) - - [QueryAllEvidenceRequest](#cosmos.evidence.v1beta1.QueryAllEvidenceRequest) - - [QueryAllEvidenceResponse](#cosmos.evidence.v1beta1.QueryAllEvidenceResponse) - - [QueryEvidenceRequest](#cosmos.evidence.v1beta1.QueryEvidenceRequest) - - [QueryEvidenceResponse](#cosmos.evidence.v1beta1.QueryEvidenceResponse) - - - [Query](#cosmos.evidence.v1beta1.Query) - -- [cosmos/evidence/v1beta1/tx.proto](#cosmos/evidence/v1beta1/tx.proto) - - [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) - - [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) - - - [Msg](#cosmos.evidence.v1beta1.Msg) - -- [cosmos/genutil/v1beta1/genesis.proto](#cosmos/genutil/v1beta1/genesis.proto) - - [GenesisState](#cosmos.genutil.v1beta1.GenesisState) +- [cosmos/distribution/v1beta1/genesis.proto](#cosmos/distribution/v1beta1/genesis.proto) + - [DelegatorStartingInfoRecord](#cosmos.distribution.v1beta1.DelegatorStartingInfoRecord) + - [DelegatorWithdrawInfo](#cosmos.distribution.v1beta1.DelegatorWithdrawInfo) + - [GenesisState](#cosmos.distribution.v1beta1.GenesisState) + - [ValidatorAccumulatedCommissionRecord](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommissionRecord) + - [ValidatorCurrentRewardsRecord](#cosmos.distribution.v1beta1.ValidatorCurrentRewardsRecord) + - [ValidatorHistoricalRewardsRecord](#cosmos.distribution.v1beta1.ValidatorHistoricalRewardsRecord) + - [ValidatorOutstandingRewardsRecord](#cosmos.distribution.v1beta1.ValidatorOutstandingRewardsRecord) + - [ValidatorSlashEventRecord](#cosmos.distribution.v1beta1.ValidatorSlashEventRecord) -- [cosmos/gov/v1beta1/gov.proto](#cosmos/gov/v1beta1/gov.proto) - - [Deposit](#cosmos.gov.v1beta1.Deposit) - - [DepositParams](#cosmos.gov.v1beta1.DepositParams) - - [Proposal](#cosmos.gov.v1beta1.Proposal) - - [TallyParams](#cosmos.gov.v1beta1.TallyParams) - - [TallyResult](#cosmos.gov.v1beta1.TallyResult) - - [TextProposal](#cosmos.gov.v1beta1.TextProposal) - - [Vote](#cosmos.gov.v1beta1.Vote) - - [VotingParams](#cosmos.gov.v1beta1.VotingParams) +- [cosmos/distribution/v1beta1/distribution.proto](#cosmos/distribution/v1beta1/distribution.proto) + - [CommunityPoolSpendProposal](#cosmos.distribution.v1beta1.CommunityPoolSpendProposal) + - [CommunityPoolSpendProposalWithDeposit](#cosmos.distribution.v1beta1.CommunityPoolSpendProposalWithDeposit) + - [DelegationDelegatorReward](#cosmos.distribution.v1beta1.DelegationDelegatorReward) + - [DelegatorStartingInfo](#cosmos.distribution.v1beta1.DelegatorStartingInfo) + - [FeePool](#cosmos.distribution.v1beta1.FeePool) + - [Params](#cosmos.distribution.v1beta1.Params) + - [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) + - [ValidatorCurrentRewards](#cosmos.distribution.v1beta1.ValidatorCurrentRewards) + - [ValidatorHistoricalRewards](#cosmos.distribution.v1beta1.ValidatorHistoricalRewards) + - [ValidatorOutstandingRewards](#cosmos.distribution.v1beta1.ValidatorOutstandingRewards) + - [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) + - [ValidatorSlashEvents](#cosmos.distribution.v1beta1.ValidatorSlashEvents) - - [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) - - [VoteOption](#cosmos.gov.v1beta1.VoteOption) +- [cosmos/upgrade/v1beta1/query.proto](#cosmos/upgrade/v1beta1/query.proto) + - [QueryAppliedPlanRequest](#cosmos.upgrade.v1beta1.QueryAppliedPlanRequest) + - [QueryAppliedPlanResponse](#cosmos.upgrade.v1beta1.QueryAppliedPlanResponse) + - [QueryCurrentPlanRequest](#cosmos.upgrade.v1beta1.QueryCurrentPlanRequest) + - [QueryCurrentPlanResponse](#cosmos.upgrade.v1beta1.QueryCurrentPlanResponse) + - [QueryUpgradedConsensusStateRequest](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateRequest) + - [QueryUpgradedConsensusStateResponse](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse) -- [cosmos/gov/v1beta1/genesis.proto](#cosmos/gov/v1beta1/genesis.proto) - - [GenesisState](#cosmos.gov.v1beta1.GenesisState) + - [Query](#cosmos.upgrade.v1beta1.Query) -- [cosmos/gov/v1beta1/query.proto](#cosmos/gov/v1beta1/query.proto) - - [QueryDepositRequest](#cosmos.gov.v1beta1.QueryDepositRequest) - - [QueryDepositResponse](#cosmos.gov.v1beta1.QueryDepositResponse) - - [QueryDepositsRequest](#cosmos.gov.v1beta1.QueryDepositsRequest) - - [QueryDepositsResponse](#cosmos.gov.v1beta1.QueryDepositsResponse) - - [QueryParamsRequest](#cosmos.gov.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.gov.v1beta1.QueryParamsResponse) - - [QueryProposalRequest](#cosmos.gov.v1beta1.QueryProposalRequest) - - [QueryProposalResponse](#cosmos.gov.v1beta1.QueryProposalResponse) - - [QueryProposalsRequest](#cosmos.gov.v1beta1.QueryProposalsRequest) - - [QueryProposalsResponse](#cosmos.gov.v1beta1.QueryProposalsResponse) - - [QueryTallyResultRequest](#cosmos.gov.v1beta1.QueryTallyResultRequest) - - [QueryTallyResultResponse](#cosmos.gov.v1beta1.QueryTallyResultResponse) - - [QueryVoteRequest](#cosmos.gov.v1beta1.QueryVoteRequest) - - [QueryVoteResponse](#cosmos.gov.v1beta1.QueryVoteResponse) - - [QueryVotesRequest](#cosmos.gov.v1beta1.QueryVotesRequest) - - [QueryVotesResponse](#cosmos.gov.v1beta1.QueryVotesResponse) +- [cosmos/upgrade/v1beta1/upgrade.proto](#cosmos/upgrade/v1beta1/upgrade.proto) + - [CancelSoftwareUpgradeProposal](#cosmos.upgrade.v1beta1.CancelSoftwareUpgradeProposal) + - [Plan](#cosmos.upgrade.v1beta1.Plan) + - [SoftwareUpgradeProposal](#cosmos.upgrade.v1beta1.SoftwareUpgradeProposal) - - [Query](#cosmos.gov.v1beta1.Query) +- [cosmos/base/kv/v1beta1/kv.proto](#cosmos/base/kv/v1beta1/kv.proto) + - [Pair](#cosmos.base.kv.v1beta1.Pair) + - [Pairs](#cosmos.base.kv.v1beta1.Pairs) -- [cosmos/gov/v1beta1/tx.proto](#cosmos/gov/v1beta1/tx.proto) - - [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) - - [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) - - [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) - - [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) - - [MsgVote](#cosmos.gov.v1beta1.MsgVote) - - [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) +- [cosmos/base/abci/v1beta1/abci.proto](#cosmos/base/abci/v1beta1/abci.proto) + - [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) + - [Attribute](#cosmos.base.abci.v1beta1.Attribute) + - [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) + - [MsgData](#cosmos.base.abci.v1beta1.MsgData) + - [Result](#cosmos.base.abci.v1beta1.Result) + - [SearchTxsResult](#cosmos.base.abci.v1beta1.SearchTxsResult) + - [SimulationResponse](#cosmos.base.abci.v1beta1.SimulationResponse) + - [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) + - [TxMsgData](#cosmos.base.abci.v1beta1.TxMsgData) + - [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) - - [Msg](#cosmos.gov.v1beta1.Msg) +- [cosmos/base/query/v1beta1/pagination.proto](#cosmos/base/query/v1beta1/pagination.proto) + - [PageRequest](#cosmos.base.query.v1beta1.PageRequest) + - [PageResponse](#cosmos.base.query.v1beta1.PageResponse) -- [cosmos/mint/v1beta1/mint.proto](#cosmos/mint/v1beta1/mint.proto) - - [Minter](#cosmos.mint.v1beta1.Minter) - - [Params](#cosmos.mint.v1beta1.Params) +- [cosmos/base/store/v1beta1/snapshot.proto](#cosmos/base/store/v1beta1/snapshot.proto) + - [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) + - [SnapshotItem](#cosmos.base.store.v1beta1.SnapshotItem) + - [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) -- [cosmos/mint/v1beta1/genesis.proto](#cosmos/mint/v1beta1/genesis.proto) - - [GenesisState](#cosmos.mint.v1beta1.GenesisState) +- [cosmos/base/store/v1beta1/commit_info.proto](#cosmos/base/store/v1beta1/commit_info.proto) + - [CommitID](#cosmos.base.store.v1beta1.CommitID) + - [CommitInfo](#cosmos.base.store.v1beta1.CommitInfo) + - [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) -- [cosmos/mint/v1beta1/query.proto](#cosmos/mint/v1beta1/query.proto) - - [QueryAnnualProvisionsRequest](#cosmos.mint.v1beta1.QueryAnnualProvisionsRequest) - - [QueryAnnualProvisionsResponse](#cosmos.mint.v1beta1.QueryAnnualProvisionsResponse) - - [QueryInflationRequest](#cosmos.mint.v1beta1.QueryInflationRequest) - - [QueryInflationResponse](#cosmos.mint.v1beta1.QueryInflationResponse) - - [QueryParamsRequest](#cosmos.mint.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.mint.v1beta1.QueryParamsResponse) +- [cosmos/base/v1beta1/coin.proto](#cosmos/base/v1beta1/coin.proto) + - [Coin](#cosmos.base.v1beta1.Coin) + - [DecCoin](#cosmos.base.v1beta1.DecCoin) + - [DecProto](#cosmos.base.v1beta1.DecProto) + - [IntProto](#cosmos.base.v1beta1.IntProto) - - [Query](#cosmos.mint.v1beta1.Query) +- [cosmos/base/tendermint/v1beta1/query.proto](#cosmos/base/tendermint/v1beta1/query.proto) + - [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) + - [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) + - [GetLatestBlockRequest](#cosmos.base.tendermint.v1beta1.GetLatestBlockRequest) + - [GetLatestBlockResponse](#cosmos.base.tendermint.v1beta1.GetLatestBlockResponse) + - [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) + - [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) + - [GetNodeInfoRequest](#cosmos.base.tendermint.v1beta1.GetNodeInfoRequest) + - [GetNodeInfoResponse](#cosmos.base.tendermint.v1beta1.GetNodeInfoResponse) + - [GetSyncingRequest](#cosmos.base.tendermint.v1beta1.GetSyncingRequest) + - [GetSyncingResponse](#cosmos.base.tendermint.v1beta1.GetSyncingResponse) + - [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) + - [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) + - [Module](#cosmos.base.tendermint.v1beta1.Module) + - [Validator](#cosmos.base.tendermint.v1beta1.Validator) + - [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) -- [cosmos/params/v1beta1/params.proto](#cosmos/params/v1beta1/params.proto) - - [ParamChange](#cosmos.params.v1beta1.ParamChange) - - [ParameterChangeProposal](#cosmos.params.v1beta1.ParameterChangeProposal) + - [Service](#cosmos.base.tendermint.v1beta1.Service) -- [cosmos/params/v1beta1/query.proto](#cosmos/params/v1beta1/query.proto) - - [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) +- [cosmos/base/snapshots/v1beta1/snapshot.proto](#cosmos/base/snapshots/v1beta1/snapshot.proto) + - [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) + - [Snapshot](#cosmos.base.snapshots.v1beta1.Snapshot) - - [Query](#cosmos.params.v1beta1.Query) +- [cosmos/base/reflection/v1beta1/reflection.proto](#cosmos/base/reflection/v1beta1/reflection.proto) + - [ListAllInterfacesRequest](#cosmos.base.reflection.v1beta1.ListAllInterfacesRequest) + - [ListAllInterfacesResponse](#cosmos.base.reflection.v1beta1.ListAllInterfacesResponse) + - [ListImplementationsRequest](#cosmos.base.reflection.v1beta1.ListImplementationsRequest) + - [ListImplementationsResponse](#cosmos.base.reflection.v1beta1.ListImplementationsResponse) + + - [ReflectionService](#cosmos.base.reflection.v1beta1.ReflectionService) - [cosmos/slashing/v1beta1/slashing.proto](#cosmos/slashing/v1beta1/slashing.proto) - [Params](#cosmos.slashing.v1beta1.Params) - [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) -- [cosmos/slashing/v1beta1/genesis.proto](#cosmos/slashing/v1beta1/genesis.proto) - - [GenesisState](#cosmos.slashing.v1beta1.GenesisState) - - [MissedBlock](#cosmos.slashing.v1beta1.MissedBlock) - - [SigningInfo](#cosmos.slashing.v1beta1.SigningInfo) - - [ValidatorMissedBlocks](#cosmos.slashing.v1beta1.ValidatorMissedBlocks) - - [cosmos/slashing/v1beta1/query.proto](#cosmos/slashing/v1beta1/query.proto) - [QueryParamsRequest](#cosmos.slashing.v1beta1.QueryParamsRequest) - [QueryParamsResponse](#cosmos.slashing.v1beta1.QueryParamsResponse) @@ -366,33 +390,47 @@ - [Msg](#cosmos.slashing.v1beta1.Msg) -- [cosmos/staking/v1beta1/staking.proto](#cosmos/staking/v1beta1/staking.proto) - - [Commission](#cosmos.staking.v1beta1.Commission) - - [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) - - [DVPair](#cosmos.staking.v1beta1.DVPair) - - [DVPairs](#cosmos.staking.v1beta1.DVPairs) - - [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) - - [DVVTriplets](#cosmos.staking.v1beta1.DVVTriplets) - - [Delegation](#cosmos.staking.v1beta1.Delegation) - - [DelegationResponse](#cosmos.staking.v1beta1.DelegationResponse) - - [Description](#cosmos.staking.v1beta1.Description) - - [HistoricalInfo](#cosmos.staking.v1beta1.HistoricalInfo) - - [Params](#cosmos.staking.v1beta1.Params) - - [Pool](#cosmos.staking.v1beta1.Pool) - - [Redelegation](#cosmos.staking.v1beta1.Redelegation) - - [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) - - [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) - - [RedelegationResponse](#cosmos.staking.v1beta1.RedelegationResponse) - - [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) - - [UnbondingDelegationEntry](#cosmos.staking.v1beta1.UnbondingDelegationEntry) - - [ValAddresses](#cosmos.staking.v1beta1.ValAddresses) - - [Validator](#cosmos.staking.v1beta1.Validator) +- [cosmos/slashing/v1beta1/genesis.proto](#cosmos/slashing/v1beta1/genesis.proto) + - [GenesisState](#cosmos.slashing.v1beta1.GenesisState) + - [MissedBlock](#cosmos.slashing.v1beta1.MissedBlock) + - [SigningInfo](#cosmos.slashing.v1beta1.SigningInfo) + - [ValidatorMissedBlocks](#cosmos.slashing.v1beta1.ValidatorMissedBlocks) - - [BondStatus](#cosmos.staking.v1beta1.BondStatus) +- [cosmos/evidence/v1beta1/evidence.proto](#cosmos/evidence/v1beta1/evidence.proto) + - [Equivocation](#cosmos.evidence.v1beta1.Equivocation) -- [cosmos/staking/v1beta1/genesis.proto](#cosmos/staking/v1beta1/genesis.proto) - - [GenesisState](#cosmos.staking.v1beta1.GenesisState) - - [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) +- [cosmos/evidence/v1beta1/query.proto](#cosmos/evidence/v1beta1/query.proto) + - [QueryAllEvidenceRequest](#cosmos.evidence.v1beta1.QueryAllEvidenceRequest) + - [QueryAllEvidenceResponse](#cosmos.evidence.v1beta1.QueryAllEvidenceResponse) + - [QueryEvidenceRequest](#cosmos.evidence.v1beta1.QueryEvidenceRequest) + - [QueryEvidenceResponse](#cosmos.evidence.v1beta1.QueryEvidenceResponse) + + - [Query](#cosmos.evidence.v1beta1.Query) + +- [cosmos/evidence/v1beta1/tx.proto](#cosmos/evidence/v1beta1/tx.proto) + - [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) + - [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) + + - [Msg](#cosmos.evidence.v1beta1.Msg) + +- [cosmos/evidence/v1beta1/genesis.proto](#cosmos/evidence/v1beta1/genesis.proto) + - [GenesisState](#cosmos.evidence.v1beta1.GenesisState) + +- [cosmos/auth/v1beta1/auth.proto](#cosmos/auth/v1beta1/auth.proto) + - [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) + - [ModuleAccount](#cosmos.auth.v1beta1.ModuleAccount) + - [Params](#cosmos.auth.v1beta1.Params) + +- [cosmos/auth/v1beta1/query.proto](#cosmos/auth/v1beta1/query.proto) + - [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) + - [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) + - [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) + + - [Query](#cosmos.auth.v1beta1.Query) + +- [cosmos/auth/v1beta1/genesis.proto](#cosmos/auth/v1beta1/genesis.proto) + - [GenesisState](#cosmos.auth.v1beta1.GenesisState) - [cosmos/staking/v1beta1/query.proto](#cosmos/staking/v1beta1/query.proto) - [QueryDelegationRequest](#cosmos.staking.v1beta1.QueryDelegationRequest) @@ -440,55 +478,33 @@ - [Msg](#cosmos.staking.v1beta1.Msg) -- [cosmos/tx/signing/v1beta1/signing.proto](#cosmos/tx/signing/v1beta1/signing.proto) - - [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) - - [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) - - [SignatureDescriptor.Data.Multi](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Multi) - - [SignatureDescriptor.Data.Single](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Single) - - [SignatureDescriptors](#cosmos.tx.signing.v1beta1.SignatureDescriptors) - - - [SignMode](#cosmos.tx.signing.v1beta1.SignMode) - -- [cosmos/tx/v1beta1/tx.proto](#cosmos/tx/v1beta1/tx.proto) - - [AuthInfo](#cosmos.tx.v1beta1.AuthInfo) - - [Fee](#cosmos.tx.v1beta1.Fee) - - [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) - - [ModeInfo.Multi](#cosmos.tx.v1beta1.ModeInfo.Multi) - - [ModeInfo.Single](#cosmos.tx.v1beta1.ModeInfo.Single) - - [SignDoc](#cosmos.tx.v1beta1.SignDoc) - - [SignerInfo](#cosmos.tx.v1beta1.SignerInfo) - - [Tx](#cosmos.tx.v1beta1.Tx) - - [TxBody](#cosmos.tx.v1beta1.TxBody) - - [TxRaw](#cosmos.tx.v1beta1.TxRaw) - -- [cosmos/tx/v1beta1/service.proto](#cosmos/tx/v1beta1/service.proto) - - [BroadcastTxRequest](#cosmos.tx.v1beta1.BroadcastTxRequest) - - [BroadcastTxResponse](#cosmos.tx.v1beta1.BroadcastTxResponse) - - [GetTxRequest](#cosmos.tx.v1beta1.GetTxRequest) - - [GetTxResponse](#cosmos.tx.v1beta1.GetTxResponse) - - [GetTxsEventRequest](#cosmos.tx.v1beta1.GetTxsEventRequest) - - [GetTxsEventResponse](#cosmos.tx.v1beta1.GetTxsEventResponse) - - [SimulateRequest](#cosmos.tx.v1beta1.SimulateRequest) - - [SimulateResponse](#cosmos.tx.v1beta1.SimulateResponse) - - - [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) - - - [Service](#cosmos.tx.v1beta1.Service) - -- [cosmos/upgrade/v1beta1/upgrade.proto](#cosmos/upgrade/v1beta1/upgrade.proto) - - [CancelSoftwareUpgradeProposal](#cosmos.upgrade.v1beta1.CancelSoftwareUpgradeProposal) - - [Plan](#cosmos.upgrade.v1beta1.Plan) - - [SoftwareUpgradeProposal](#cosmos.upgrade.v1beta1.SoftwareUpgradeProposal) +- [cosmos/staking/v1beta1/genesis.proto](#cosmos/staking/v1beta1/genesis.proto) + - [GenesisState](#cosmos.staking.v1beta1.GenesisState) + - [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) -- [cosmos/upgrade/v1beta1/query.proto](#cosmos/upgrade/v1beta1/query.proto) - - [QueryAppliedPlanRequest](#cosmos.upgrade.v1beta1.QueryAppliedPlanRequest) - - [QueryAppliedPlanResponse](#cosmos.upgrade.v1beta1.QueryAppliedPlanResponse) - - [QueryCurrentPlanRequest](#cosmos.upgrade.v1beta1.QueryCurrentPlanRequest) - - [QueryCurrentPlanResponse](#cosmos.upgrade.v1beta1.QueryCurrentPlanResponse) - - [QueryUpgradedConsensusStateRequest](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateRequest) - - [QueryUpgradedConsensusStateResponse](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse) +- [cosmos/staking/v1beta1/staking.proto](#cosmos/staking/v1beta1/staking.proto) + - [Commission](#cosmos.staking.v1beta1.Commission) + - [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) + - [DVPair](#cosmos.staking.v1beta1.DVPair) + - [DVPairs](#cosmos.staking.v1beta1.DVPairs) + - [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) + - [DVVTriplets](#cosmos.staking.v1beta1.DVVTriplets) + - [Delegation](#cosmos.staking.v1beta1.Delegation) + - [DelegationResponse](#cosmos.staking.v1beta1.DelegationResponse) + - [Description](#cosmos.staking.v1beta1.Description) + - [HistoricalInfo](#cosmos.staking.v1beta1.HistoricalInfo) + - [Params](#cosmos.staking.v1beta1.Params) + - [Pool](#cosmos.staking.v1beta1.Pool) + - [Redelegation](#cosmos.staking.v1beta1.Redelegation) + - [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) + - [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) + - [RedelegationResponse](#cosmos.staking.v1beta1.RedelegationResponse) + - [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) + - [UnbondingDelegationEntry](#cosmos.staking.v1beta1.UnbondingDelegationEntry) + - [ValAddresses](#cosmos.staking.v1beta1.ValAddresses) + - [Validator](#cosmos.staking.v1beta1.Validator) - - [Query](#cosmos.upgrade.v1beta1.Query) + - [BondStatus](#cosmos.staking.v1beta1.BondStatus) - [cosmos/vesting/v1beta1/tx.proto](#cosmos/vesting/v1beta1/tx.proto) - [MsgCreateVestingAccount](#cosmos.vesting.v1beta1.MsgCreateVestingAccount) @@ -503,13 +519,15 @@ - [Period](#cosmos.vesting.v1beta1.Period) - [PeriodicVestingAccount](#cosmos.vesting.v1beta1.PeriodicVestingAccount) -- [ibc/applications/transfer/v1/transfer.proto](#ibc/applications/transfer/v1/transfer.proto) - - [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) - - [FungibleTokenPacketData](#ibc.applications.transfer.v1.FungibleTokenPacketData) - - [Params](#ibc.applications.transfer.v1.Params) +- [cosmos/params/v1beta1/query.proto](#cosmos/params/v1beta1/query.proto) + - [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) -- [ibc/applications/transfer/v1/genesis.proto](#ibc/applications/transfer/v1/genesis.proto) - - [GenesisState](#ibc.applications.transfer.v1.GenesisState) + - [Query](#cosmos.params.v1beta1.Query) + +- [cosmos/params/v1beta1/params.proto](#cosmos/params/v1beta1/params.proto) + - [ParamChange](#cosmos.params.v1beta1.ParamChange) + - [ParameterChangeProposal](#cosmos.params.v1beta1.ParameterChangeProposal) - [ibc/applications/transfer/v1/query.proto](#ibc/applications/transfer/v1/query.proto) - [QueryDenomTraceRequest](#ibc.applications.transfer.v1.QueryDenomTraceRequest) @@ -521,6 +539,20 @@ - [Query](#ibc.applications.transfer.v1.Query) +- [ibc/applications/transfer/v1/tx.proto](#ibc/applications/transfer/v1/tx.proto) + - [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) + - [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) + + - [Msg](#ibc.applications.transfer.v1.Msg) + +- [ibc/applications/transfer/v1/transfer.proto](#ibc/applications/transfer/v1/transfer.proto) + - [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) + - [FungibleTokenPacketData](#ibc.applications.transfer.v1.FungibleTokenPacketData) + - [Params](#ibc.applications.transfer.v1.Params) + +- [ibc/applications/transfer/v1/genesis.proto](#ibc/applications/transfer/v1/genesis.proto) + - [GenesisState](#ibc.applications.transfer.v1.GenesisState) + - [ibc/core/client/v1/client.proto](#ibc/core/client/v1/client.proto) - [ClientConsensusStates](#ibc.core.client.v1.ClientConsensusStates) - [ClientUpdateProposal](#ibc.core.client.v1.ClientUpdateProposal) @@ -529,11 +561,36 @@ - [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) - [Params](#ibc.core.client.v1.Params) -- [ibc/applications/transfer/v1/tx.proto](#ibc/applications/transfer/v1/tx.proto) - - [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) - - [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) +- [ibc/core/client/v1/query.proto](#ibc/core/client/v1/query.proto) + - [QueryClientParamsRequest](#ibc.core.client.v1.QueryClientParamsRequest) + - [QueryClientParamsResponse](#ibc.core.client.v1.QueryClientParamsResponse) + - [QueryClientStateRequest](#ibc.core.client.v1.QueryClientStateRequest) + - [QueryClientStateResponse](#ibc.core.client.v1.QueryClientStateResponse) + - [QueryClientStatesRequest](#ibc.core.client.v1.QueryClientStatesRequest) + - [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse) + - [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest) + - [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) + - [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) + - [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) - - [Msg](#ibc.applications.transfer.v1.Msg) + - [Query](#ibc.core.client.v1.Query) + +- [ibc/core/client/v1/tx.proto](#ibc/core/client/v1/tx.proto) + - [MsgCreateClient](#ibc.core.client.v1.MsgCreateClient) + - [MsgCreateClientResponse](#ibc.core.client.v1.MsgCreateClientResponse) + - [MsgSubmitMisbehaviour](#ibc.core.client.v1.MsgSubmitMisbehaviour) + - [MsgSubmitMisbehaviourResponse](#ibc.core.client.v1.MsgSubmitMisbehaviourResponse) + - [MsgUpdateClient](#ibc.core.client.v1.MsgUpdateClient) + - [MsgUpdateClientResponse](#ibc.core.client.v1.MsgUpdateClientResponse) + - [MsgUpgradeClient](#ibc.core.client.v1.MsgUpgradeClient) + - [MsgUpgradeClientResponse](#ibc.core.client.v1.MsgUpgradeClientResponse) + + - [Msg](#ibc.core.client.v1.Msg) + +- [ibc/core/client/v1/genesis.proto](#ibc/core/client/v1/genesis.proto) + - [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) + - [GenesisState](#ibc.core.client.v1.GenesisState) + - [IdentifiedGenesisMetadata](#ibc.core.client.v1.IdentifiedGenesisMetadata) - [ibc/core/channel/v1/channel.proto](#ibc/core/channel/v1/channel.proto) - [Acknowledgement](#ibc.core.channel.v1.Acknowledgement) @@ -546,10 +603,6 @@ - [Order](#ibc.core.channel.v1.Order) - [State](#ibc.core.channel.v1.State) -- [ibc/core/channel/v1/genesis.proto](#ibc/core/channel/v1/genesis.proto) - - [GenesisState](#ibc.core.channel.v1.GenesisState) - - [PacketSequence](#ibc.core.channel.v1.PacketSequence) - - [ibc/core/channel/v1/query.proto](#ibc/core/channel/v1/query.proto) - [QueryChannelClientStateRequest](#ibc.core.channel.v1.QueryChannelClientStateRequest) - [QueryChannelClientStateResponse](#ibc.core.channel.v1.QueryChannelClientStateResponse) @@ -604,36 +657,9 @@ - [Msg](#ibc.core.channel.v1.Msg) -- [ibc/core/client/v1/genesis.proto](#ibc/core/client/v1/genesis.proto) - - [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) - - [GenesisState](#ibc.core.client.v1.GenesisState) - - [IdentifiedGenesisMetadata](#ibc.core.client.v1.IdentifiedGenesisMetadata) - -- [ibc/core/client/v1/query.proto](#ibc/core/client/v1/query.proto) - - [QueryClientParamsRequest](#ibc.core.client.v1.QueryClientParamsRequest) - - [QueryClientParamsResponse](#ibc.core.client.v1.QueryClientParamsResponse) - - [QueryClientStateRequest](#ibc.core.client.v1.QueryClientStateRequest) - - [QueryClientStateResponse](#ibc.core.client.v1.QueryClientStateResponse) - - [QueryClientStatesRequest](#ibc.core.client.v1.QueryClientStatesRequest) - - [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse) - - [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest) - - [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) - - [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) - - [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) - - - [Query](#ibc.core.client.v1.Query) - -- [ibc/core/client/v1/tx.proto](#ibc/core/client/v1/tx.proto) - - [MsgCreateClient](#ibc.core.client.v1.MsgCreateClient) - - [MsgCreateClientResponse](#ibc.core.client.v1.MsgCreateClientResponse) - - [MsgSubmitMisbehaviour](#ibc.core.client.v1.MsgSubmitMisbehaviour) - - [MsgSubmitMisbehaviourResponse](#ibc.core.client.v1.MsgSubmitMisbehaviourResponse) - - [MsgUpdateClient](#ibc.core.client.v1.MsgUpdateClient) - - [MsgUpdateClientResponse](#ibc.core.client.v1.MsgUpdateClientResponse) - - [MsgUpgradeClient](#ibc.core.client.v1.MsgUpgradeClient) - - [MsgUpgradeClientResponse](#ibc.core.client.v1.MsgUpgradeClientResponse) - - - [Msg](#ibc.core.client.v1.Msg) +- [ibc/core/channel/v1/genesis.proto](#ibc/core/channel/v1/genesis.proto) + - [GenesisState](#ibc.core.channel.v1.GenesisState) + - [PacketSequence](#ibc.core.channel.v1.PacketSequence) - [ibc/core/commitment/v1/commitment.proto](#ibc/core/commitment/v1/commitment.proto) - [MerklePath](#ibc.core.commitment.v1.MerklePath) @@ -651,9 +677,6 @@ - [State](#ibc.core.connection.v1.State) -- [ibc/core/connection/v1/genesis.proto](#ibc/core/connection/v1/genesis.proto) - - [GenesisState](#ibc.core.connection.v1.GenesisState) - - [ibc/core/connection/v1/query.proto](#ibc/core/connection/v1/query.proto) - [QueryClientConnectionsRequest](#ibc.core.connection.v1.QueryClientConnectionsRequest) - [QueryClientConnectionsResponse](#ibc.core.connection.v1.QueryClientConnectionsResponse) @@ -680,12 +703,22 @@ - [Msg](#ibc.core.connection.v1.Msg) +- [ibc/core/connection/v1/genesis.proto](#ibc/core/connection/v1/genesis.proto) + - [GenesisState](#ibc.core.connection.v1.GenesisState) + - [ibc/core/types/v1/genesis.proto](#ibc/core/types/v1/genesis.proto) - [GenesisState](#ibc.core.types.v1.GenesisState) - [ibc/lightclients/localhost/v1/localhost.proto](#ibc/lightclients/localhost/v1/localhost.proto) - [ClientState](#ibc.lightclients.localhost.v1.ClientState) +- [ibc/lightclients/tendermint/v1/tendermint.proto](#ibc/lightclients/tendermint/v1/tendermint.proto) + - [ClientState](#ibc.lightclients.tendermint.v1.ClientState) + - [ConsensusState](#ibc.lightclients.tendermint.v1.ConsensusState) + - [Fraction](#ibc.lightclients.tendermint.v1.Fraction) + - [Header](#ibc.lightclients.tendermint.v1.Header) + - [Misbehaviour](#ibc.lightclients.tendermint.v1.Misbehaviour) + - [ibc/lightclients/solomachine/v1/solomachine.proto](#ibc/lightclients/solomachine/v1/solomachine.proto) - [ChannelStateData](#ibc.lightclients.solomachine.v1.ChannelStateData) - [ClientState](#ibc.lightclients.solomachine.v1.ClientState) @@ -706,106 +739,190 @@ - [DataType](#ibc.lightclients.solomachine.v1.DataType) -- [ibc/lightclients/tendermint/v1/tendermint.proto](#ibc/lightclients/tendermint/v1/tendermint.proto) - - [ClientState](#ibc.lightclients.tendermint.v1.ClientState) - - [ConsensusState](#ibc.lightclients.tendermint.v1.ConsensusState) - - [Fraction](#ibc.lightclients.tendermint.v1.Fraction) - - [Header](#ibc.lightclients.tendermint.v1.Header) - - [Misbehaviour](#ibc.lightclients.tendermint.v1.Misbehaviour) - - [Scalar Value Types](#scalar-value-types) - +

      Top

      -## cosmos/auth/v1beta1/auth.proto +## cosmos/tx/v1beta1/tx.proto - + -### BaseAccount -BaseAccount defines a base account type. It contains all the necessary fields -for basic account functionality. Any custom account type should extend this -type for additional functionality (e.g. vesting). +### AuthInfo +AuthInfo describes the fee and signer modes that are used to sign a +transaction. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `account_number` | [uint64](#uint64) | | | -| `sequence` | [uint64](#uint64) | | | +| `signer_infos` | [SignerInfo](#cosmos.tx.v1beta1.SignerInfo) | repeated | signer_infos defines the signing modes for the required signers. The number and order of elements must match the required signers from TxBody's messages. The first element is the primary signer and the one which pays the fee. | +| `fee` | [Fee](#cosmos.tx.v1beta1.Fee) | | Fee is the fee and gas limit for the transaction. The first signer is the primary signer and the one which pays the fee. The fee can be calculated based on the cost of evaluating the body and doing signature verification of the signers. This can be estimated via simulation. | - + -### ModuleAccount -ModuleAccount defines an account for modules that holds coins on a pool. +### Fee +Fee includes the amount of coins paid in fees and the maximum +gas to be used by the transaction. The ratio yields an effective "gasprice", +which must be above some miminum to be accepted into the mempool. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `base_account` | [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) | | | -| `name` | [string](#string) | | | -| `permissions` | [string](#string) | repeated | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | amount is the amount of coins to be paid as a fee | +| `gas_limit` | [uint64](#uint64) | | gas_limit is the maximum gas that can be used in transaction processing before an out of gas error occurs | +| `payer` | [string](#string) | | if unset, the first signer is responsible for paying the fees. If set, the specified account must pay the fees. the payer must be a tx signer (and thus have signed this field in AuthInfo). setting this field does *not* change the ordering of required signers for the transaction. | +| `granter` | [string](#string) | | if set, the fee payer (either the first signer or the value of the payer field) requests that a fee grant be used to pay fees instead of the fee payer's own balance. If an appropriate fee grant does not exist or the chain does not support fee grants, this will fail | - + -### Params -Params defines the parameters for the auth module. +### ModeInfo +ModeInfo describes the signing mode of a single or nested multisig signer. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `max_memo_characters` | [uint64](#uint64) | | | -| `tx_sig_limit` | [uint64](#uint64) | | | -| `tx_size_cost_per_byte` | [uint64](#uint64) | | | -| `sig_verify_cost_ed25519` | [uint64](#uint64) | | | -| `sig_verify_cost_secp256k1` | [uint64](#uint64) | | | +| `single` | [ModeInfo.Single](#cosmos.tx.v1beta1.ModeInfo.Single) | | single represents a single signer | +| `multi` | [ModeInfo.Multi](#cosmos.tx.v1beta1.ModeInfo.Multi) | | multi represents a nested multisig signer | + + + + + + + + +### ModeInfo.Multi +Multi is the mode info for a multisig public key + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `bitarray` | [cosmos.crypto.multisig.v1beta1.CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) | | bitarray specifies which keys within the multisig are signing | +| `mode_infos` | [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) | repeated | mode_infos is the corresponding modes of the signers of the multisig which could include nested multisig public keys | + + + + + + + + +### ModeInfo.Single +Single is the mode info for a single signer. It is structured as a message +to allow for additional fields such as locale for SIGN_MODE_TEXTUAL in the +future + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `mode` | [cosmos.tx.signing.v1beta1.SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | + + + + + + + + +### SignDoc +SignDoc is the type used for generating sign bytes for SIGN_MODE_DIRECT. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `body_bytes` | [bytes](#bytes) | | body_bytes is protobuf serialization of a TxBody that matches the representation in TxRaw. | +| `auth_info_bytes` | [bytes](#bytes) | | auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in TxRaw. | +| `chain_id` | [string](#string) | | chain_id is the unique identifier of the chain this transaction targets. It prevents signed transactions from being used on another chain by an attacker | +| `account_number` | [uint64](#uint64) | | account_number is the account number of the account in state | + + + + + + + + +### SignerInfo +SignerInfo describes the public key and signing mode of a single top-level +signer. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public_key is the public key of the signer. It is optional for accounts that already exist in state. If unset, the verifier can use the required \ signer address for this position and lookup the public key. | +| `mode_info` | [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) | | mode_info describes the signing mode of the signer and is a nested structure to support nested multisig pubkey's | +| `sequence` | [uint64](#uint64) | | sequence is the sequence of the account, which describes the number of committed transactions signed by a given address. It is used to prevent replay attacks. | + + + + + + + + +### Tx +Tx is the standard type used for broadcasting transactions. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `body` | [TxBody](#cosmos.tx.v1beta1.TxBody) | | body is the processable content of the transaction | +| `auth_info` | [AuthInfo](#cosmos.tx.v1beta1.AuthInfo) | | auth_info is the authorization related content of the transaction, specifically signers, signer modes and fee | +| `signatures` | [bytes](#bytes) | repeated | signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to allow connecting signature meta information like public key and signing mode by position. | - - + - +### TxBody +TxBody is the body of a transaction that all signers sign over. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `messages` | [google.protobuf.Any](#google.protobuf.Any) | repeated | messages is a list of messages to be executed. The required signers of those messages define the number and order of elements in AuthInfo's signer_infos and Tx's signatures. Each required signer address is added to the list only the first time it occurs. By convention, the first required signer (usually from the first message) is referred to as the primary signer and pays the fee for the whole transaction. | +| `memo` | [string](#string) | | memo is any arbitrary memo to be added to the transaction | +| `timeout_height` | [uint64](#uint64) | | timeout is the block height after which this transaction will not be processed by the chain | +| `extension_options` | [google.protobuf.Any](#google.protobuf.Any) | repeated | extension_options are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, the transaction will be rejected | +| `non_critical_extension_options` | [google.protobuf.Any](#google.protobuf.Any) | repeated | extension_options are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, they will be ignored | - -

      Top

      -## cosmos/auth/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the auth module's genesis state. +### TxRaw +TxRaw is a variant of Tx that pins the signer's exact binary representation +of body and auth_info. This is used for signing, broadcasting and +verification. The binary `serialize(tx: TxRaw)` is stored in Tendermint and +the hash `sha256(serialize(tx: TxRaw))` becomes the "txhash", commonly used +as the transaction ID. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines all the paramaters of the module. | -| `accounts` | [google.protobuf.Any](#google.protobuf.Any) | repeated | accounts are the accounts present at genesis. | +| `body_bytes` | [bytes](#bytes) | | body_bytes is a protobuf serialization of a TxBody that matches the representation in SignDoc. | +| `auth_info_bytes` | [bytes](#bytes) | | auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in SignDoc. | +| `signatures` | [bytes](#bytes) | repeated | signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to allow connecting signature meta information like public key and signing mode by position. | @@ -821,157 +938,140 @@ GenesisState defines the auth module's genesis state. - +

      Top

      -## cosmos/auth/v1beta1/query.proto +## cosmos/tx/v1beta1/service.proto - + -### QueryAccountRequest -QueryAccountRequest is the request type for the Query/Account RPC method. +### BroadcastTxRequest +BroadcastTxRequest is the request type for the Service.BroadcastTxRequest +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address defines the address to query for. | +| `tx_bytes` | [bytes](#bytes) | | tx_bytes is the raw transaction. | +| `mode` | [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) | | | - + -### QueryAccountResponse -QueryAccountResponse is the response type for the Query/Account RPC method. +### BroadcastTxResponse +BroadcastTxResponse is the response type for the +Service.BroadcastTx method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `account` | [google.protobuf.Any](#google.protobuf.Any) | | account defines the account of the corresponding address. | - - - - - - - - -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. +| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | - + -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method. +### GetTxRequest +GetTxRequest is the request type for the Service.GetTx +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines the parameters of the module. | - - - - - - +| `hash` | [string](#string) | | hash is the tx hash to query, encoded as a hex string. | - - - -### Query -Query defines the gRPC querier service. -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Account` | [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) | [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) | Account returns account details based on address. | GET|/cosmos/auth/v1beta1/accounts/{address}| -| `Params` | [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) | Params queries all parameters. | GET|/cosmos/auth/v1beta1/params| + - +### GetTxResponse +GetTxResponse is the response type for the Service.GetTx method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the queried transaction. | +| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | - -

      Top

      -## cosmos/base/v1beta1/coin.proto - -### Coin -Coin defines a token with a denomination and an amount. + -NOTE: The amount field is an Int which implements the custom method -signatures required by gogoproto. +### GetTxsEventRequest +GetTxsEventRequest is the request type for the Service.TxsByEvents +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | | -| `amount` | [string](#string) | | | - +| `events` | [string](#string) | repeated | events is the list of transaction event type. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - -### DecCoin -DecCoin defines a token with a denomination and a decimal amount. + -NOTE: The amount field is an Dec which implements the custom method -signatures required by gogoproto. +### GetTxsEventResponse +GetTxsEventResponse is the response type for the Service.TxsByEvents +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | | -| `amount` | [string](#string) | | | +| `txs` | [Tx](#cosmos.tx.v1beta1.Tx) | repeated | txs is the list of queried transactions. | +| `tx_responses` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | tx_responses is the list of queried TxResponses. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | - + -### DecProto -DecProto defines a Protobuf wrapper around a Dec object. +### SimulateRequest +SimulateRequest is the request type for the Service.Simulate +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `dec` | [string](#string) | | | +| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the transaction to simulate. | - + -### IntProto -IntProto defines a Protobuf wrapper around an Int object. +### SimulateResponse +SimulateResponse is the response type for the +Service.SimulateRPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `int` | [string](#string) | | | +| `gas_info` | [cosmos.base.abci.v1beta1.GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | gas_info is the information about gas used in the simulation. | +| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | result is the result of the simulation. | @@ -979,261 +1079,257 @@ IntProto defines a Protobuf wrapper around an Int object. - - + - +### BroadcastMode +BroadcastMode specifies the broadcast mode for the TxService.Broadcast RPC method. +| Name | Number | Description | +| ---- | ------ | ----------- | +| BROADCAST_MODE_UNSPECIFIED | 0 | zero-value for mode ordering | +| BROADCAST_MODE_BLOCK | 1 | BROADCAST_MODE_BLOCK defines a tx broadcasting mode where the client waits for the tx to be committed in a block. | +| BROADCAST_MODE_SYNC | 2 | BROADCAST_MODE_SYNC defines a tx broadcasting mode where the client waits for a CheckTx execution response only. | +| BROADCAST_MODE_ASYNC | 3 | BROADCAST_MODE_ASYNC defines a tx broadcasting mode where the client returns immediately. | - -

      Top

      + -## cosmos/authz/v1beta1/authz.proto + + - +### Service +Service defines a gRPC service for interacting with transactions. -### AuthorizationGrant -AuthorizationGrant gives permissions to execute -the provide method with expiration time. +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Simulate` | [SimulateRequest](#cosmos.tx.v1beta1.SimulateRequest) | [SimulateResponse](#cosmos.tx.v1beta1.SimulateResponse) | Simulate simulates executing a transaction for estimating gas usage. | POST|/cosmos/tx/v1beta1/simulate| +| `GetTx` | [GetTxRequest](#cosmos.tx.v1beta1.GetTxRequest) | [GetTxResponse](#cosmos.tx.v1beta1.GetTxResponse) | GetTx fetches a tx by hash. | GET|/cosmos/tx/v1beta1/txs/{hash}| +| `BroadcastTx` | [BroadcastTxRequest](#cosmos.tx.v1beta1.BroadcastTxRequest) | [BroadcastTxResponse](#cosmos.tx.v1beta1.BroadcastTxResponse) | BroadcastTx broadcast transaction. | POST|/cosmos/tx/v1beta1/txs| +| `GetTxsEvent` | [GetTxsEventRequest](#cosmos.tx.v1beta1.GetTxsEventRequest) | [GetTxsEventResponse](#cosmos.tx.v1beta1.GetTxsEventResponse) | GetTxsEvent fetches txs by event. | GET|/cosmos/tx/v1beta1/txs| + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | + +

      Top

      +## cosmos/tx/signing/v1beta1/signing.proto - + -### GenericAuthorization -GenericAuthorization gives the grantee unrestricted permissions to execute -the provided method on behalf of the granter's account. +### SignatureDescriptor +SignatureDescriptor is a convenience type which represents the full data for +a signature including the public key of the signer, signing modes and the +signature itself. It is primarily used for coordinating signatures between +clients. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `method_name` | [string](#string) | | method name to grant unrestricted permissions to execute Note: MethodName() is already a method on `GenericAuthorization` type, we need some custom naming here so using `MessageName` | +| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public_key is the public key of the signer | +| `data` | [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) | | | +| `sequence` | [uint64](#uint64) | | sequence is the sequence of the account, which describes the number of committed transactions signed by a given address. It is used to prevent replay attacks. | - + -### SendAuthorization -SendAuthorization allows the grantee to spend up to spend_limit coins from -the granter's account. +### SignatureDescriptor.Data +Data represents signature data | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `single` | [SignatureDescriptor.Data.Single](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Single) | | single represents a single signer | +| `multi` | [SignatureDescriptor.Data.Multi](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Multi) | | multi represents a multisig signer | - - + - +### SignatureDescriptor.Data.Multi +Multi is the signature data for a multisig public key - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `bitarray` | [cosmos.crypto.multisig.v1beta1.CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) | | bitarray specifies which keys within the multisig are signing | +| `signatures` | [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) | repeated | signatures is the signatures of the multi-signature | - -

      Top

      -## cosmos/base/abci/v1beta1/abci.proto - + -### ABCIMessageLog -ABCIMessageLog defines a structure containing an indexed tx ABCI message log. +### SignatureDescriptor.Data.Single +Single is the signature data for a single signer | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `msg_index` | [uint32](#uint32) | | | -| `log` | [string](#string) | | | -| `events` | [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) | repeated | Events contains a slice of Event objects that were emitted during some execution. | +| `mode` | [SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | +| `signature` | [bytes](#bytes) | | signature is the raw signature bytes | - + -### Attribute -Attribute defines an attribute wrapper where the key and value are -strings instead of raw bytes. +### SignatureDescriptors +SignatureDescriptors wraps multiple SignatureDescriptor's. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [string](#string) | | | -| `value` | [string](#string) | | | - - - - +| `signatures` | [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) | repeated | signatures are the signature descriptors | - -### GasInfo -GasInfo defines tx execution gas context. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `gas_wanted` | [uint64](#uint64) | | GasWanted is the maximum units of work we allow this tx to perform. | -| `gas_used` | [uint64](#uint64) | | GasUsed is the amount of gas actually consumed. | + + +### SignMode +SignMode represents a signing mode with its own security guarantees. +| Name | Number | Description | +| ---- | ------ | ----------- | +| SIGN_MODE_UNSPECIFIED | 0 | SIGN_MODE_UNSPECIFIED specifies an unknown signing mode and will be rejected | +| SIGN_MODE_DIRECT | 1 | SIGN_MODE_DIRECT specifies a signing mode which uses SignDoc and is verified with raw bytes from Tx | +| SIGN_MODE_TEXTUAL | 2 | SIGN_MODE_TEXTUAL is a future signing mode that will verify some human-readable textual representation on top of the binary representation from SIGN_MODE_DIRECT | +| SIGN_MODE_LEGACY_AMINO_JSON | 127 | SIGN_MODE_LEGACY_AMINO_JSON is a backwards compatibility mode which uses Amino JSON and will be removed in the future | - + -### MsgData -MsgData defines the data returned in a Result object during message -execution. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `msg_type` | [string](#string) | | | -| `data` | [bytes](#bytes) | | | + +

      Top

      +## cosmos/crisis/v1beta1/tx.proto - + -### Result -Result is the union of ResponseFormat and ResponseCheckTx. +### MsgVerifyInvariant +MsgVerifyInvariant represents a message to verify a particular invariance. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `data` | [bytes](#bytes) | | Data is any data returned from message or handler execution. It MUST be length prefixed in order to separate data from multiple message executions. | -| `log` | [string](#string) | | Log contains the log information from message or handler execution. | -| `events` | [tendermint.abci.Event](#tendermint.abci.Event) | repeated | Events contains a slice of Event objects that were emitted during message or handler execution. | +| `sender` | [string](#string) | | | +| `invariant_module_name` | [string](#string) | | | +| `invariant_route` | [string](#string) | | | - + -### SearchTxsResult -SearchTxsResult defines a structure for querying txs pageable +### MsgVerifyInvariantResponse +MsgVerifyInvariantResponse defines the Msg/VerifyInvariant response type. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `total_count` | [uint64](#uint64) | | Count of all txs | -| `count` | [uint64](#uint64) | | Count of txs in current page | -| `page_number` | [uint64](#uint64) | | Index of current page, start from 1 | -| `page_total` | [uint64](#uint64) | | Count of total pages | -| `limit` | [uint64](#uint64) | | Max count txs per page | -| `txs` | [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | List of txs in current page | + + + + - + -### SimulationResponse -SimulationResponse defines the response generated when a transaction is -successfully simulated. +### Msg +Msg defines the bank Msg service. +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `VerifyInvariant` | [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) | [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) | VerifyInvariant defines a method to verify a particular invariance. | | -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `gas_info` | [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | | -| `result` | [Result](#cosmos.base.abci.v1beta1.Result) | | | + + +

      Top

      +## cosmos/crisis/v1beta1/genesis.proto - -### StringEvent -StringEvent defines en Event object wrapper where all the attributes -contain key/value pairs that are strings instead of raw bytes. + + +### GenesisState +GenesisState defines the crisis module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `type` | [string](#string) | | | -| `attributes` | [Attribute](#cosmos.base.abci.v1beta1.Attribute) | repeated | | +| `constant_fee` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | constant_fee is the fee used to verify the invariant in the crisis module. | + - + -### TxMsgData -TxMsgData defines a list of MsgData. A transaction will have a MsgData object -for each message. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | | + +

      Top

      +## cosmos/crypto/multisig/keys.proto - + -### TxResponse -TxResponse defines a structure containing relevant tx data and metadata. The -tags are stringified and the log is JSON decoded. +### LegacyAminoPubKey +LegacyAminoPubKey specifies a public key type +which nests multiple public keys and a threshold, +it uses legacy amino address rules. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | The block height | -| `txhash` | [string](#string) | | The transaction hash. | -| `codespace` | [string](#string) | | Namespace for the Code | -| `code` | [uint32](#uint32) | | Response code. | -| `data` | [string](#string) | | Result bytes, if any. | -| `raw_log` | [string](#string) | | The output of the application's logger (raw string). May be non-deterministic. | -| `logs` | [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) | repeated | The output of the application's logger (typed). May be non-deterministic. | -| `info` | [string](#string) | | Additional information. May be non-deterministic. | -| `gas_wanted` | [int64](#int64) | | Amount of gas requested for transaction. | -| `gas_used` | [int64](#int64) | | Amount of gas consumed by transaction. | -| `tx` | [google.protobuf.Any](#google.protobuf.Any) | | The request transaction bytes. | -| `timestamp` | [string](#string) | | Time of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time. | +| `threshold` | [uint32](#uint32) | | | +| `public_keys` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | @@ -1249,97 +1345,93 @@ tags are stringified and the log is JSON decoded. - +

      Top

      -## cosmos/authz/v1beta1/tx.proto +## cosmos/crypto/multisig/v1beta1/multisig.proto - + -### MsgExecAuthorizedRequest -MsgExecAuthorizedRequest attempts to execute the provided messages using -authorizations granted to the grantee. Each message should have only -one signer corresponding to the granter of the authorization. +### CompactBitArray +CompactBitArray is an implementation of a space efficient bit array. +This is used to ensure that the encoded data takes up a minimal amount of +space after proto encoding. +This is not thread safe, and is not intended for concurrent usage. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `grantee` | [string](#string) | | | -| `msgs` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | +| `extra_bits_stored` | [uint32](#uint32) | | | +| `elems` | [bytes](#bytes) | | | - + -### MsgExecAuthorizedResponse -MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse response type. +### MultiSignature +MultiSignature wraps the signatures from a multisig.LegacyAminoPubKey. +See cosmos.tx.v1betata1.ModeInfo.Multi for how to specify which signers +signed and with which modes. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | | - - - - - - - - -### MsgGrantAuthorizationRequest -MsgGrantAuthorizationRequest grants the provided authorization to the grantee on the granter's -account with the provided expiration time. +| `signatures` | [bytes](#bytes) | repeated | | -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | + + + - + -### MsgGrantAuthorizationResponse -MsgGrantAuthorizationResponse defines the Msg/MsgGrantAuthorization response type. + +

      Top

      +## cosmos/crypto/secp256k1/keys.proto - + -### MsgRevokeAuthorizationRequest -MsgRevokeAuthorizationRequest revokes any authorization with the provided sdk.Msg type on the -granter's account with that has been granted to the grantee. +### PrivKey +PrivKey defines a secp256k1 private key. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `method_name` | [string](#string) | | | +| `key` | [bytes](#bytes) | | | - + -### MsgRevokeAuthorizationResponse -MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse response type. +### PubKey +PubKey defines a secp256k1 public key +Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte +if the y-coordinate is the lexicographically largest of the two associated with +the x-coordinate. Otherwise the first byte is a 0x03. +This prefix is followed with the x-coordinate. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | | @@ -1351,56 +1443,45 @@ MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse re - - - -### Msg -Msg defines the authz Msg service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `GrantAuthorization` | [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) | [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) | GrantAuthorization grants the provided authorization to the grantee on the granter's account with the provided expiration time. | | -| `ExecAuthorized` | [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) | [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) | ExecAuthorized attempts to execute the provided messages using authorizations granted to the grantee. Each message should have only one signer corresponding to the granter of the authorization. | | -| `RevokeAuthorization` | [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) | [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) | RevokeAuthorization revokes any authorization corresponding to the provided method name on the granter's account that has been granted to the grantee. | | - - +

      Top

      -## cosmos/authz/v1beta1/genesis.proto +## cosmos/crypto/ed25519/keys.proto - + -### GenesisState -GenesisState defines the authz module's genesis state. +### PrivKey +PrivKey defines a ed25519 private key. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorization` | [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) | repeated | | +| `key` | [bytes](#bytes) | | | - + -### GrantAuthorization -GrantAuthorization defines the GenesisState/GrantAuthorization type. +### PubKey +PubKey defines a ed25519 public key +Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte +if the y-coordinate is the lexicographically largest of the two associated with +the x-coordinate. Otherwise the first byte is a 0x03. +This prefix is followed with the x-coordinate. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `key` | [bytes](#bytes) | | | @@ -1408,142 +1489,137 @@ GrantAuthorization defines the GenesisState/GrantAuthorization type. - + + + + + + + + + +

      Top

      + +## cosmos/mint/v1beta1/query.proto - - + +### QueryAnnualProvisionsRequest +QueryAnnualProvisionsRequest is the request type for the +Query/AnnualProvisions RPC method. - -

      Top

      -## cosmos/base/query/v1beta1/pagination.proto - -### PageRequest -PageRequest is to be embedded in gRPC request messages for efficient -pagination. Ex: + - message SomeRequest { - Foo some_parameter = 1; - PageRequest pagination = 2; - } +### QueryAnnualProvisionsResponse +QueryAnnualProvisionsResponse is the response type for the +Query/AnnualProvisions RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | key is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be set. | -| `offset` | [uint64](#uint64) | | offset is a numeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be set. | -| `limit` | [uint64](#uint64) | | limit is the total number of results to be returned in the result page. If left empty it will default to a value to be set by each app. | -| `count_total` | [bool](#bool) | | count_total is set to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. count_total is only respected when offset is used. It is ignored when key is set. | - +| `annual_provisions` | [bytes](#bytes) | | annual_provisions is the current minting annual provisions value. | - -### PageResponse -PageResponse is to be embedded in gRPC response messages where the -corresponding request message has used PageRequest. + - message SomeResponse { - repeated Bar results = 1; - PageResponse page = 2; - } +### QueryInflationRequest +QueryInflationRequest is the request type for the Query/Inflation RPC method. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `next_key` | [bytes](#bytes) | | next_key is the key to be passed to PageRequest.key to query the next page most efficiently | -| `total` | [uint64](#uint64) | | total is total number of results available if PageRequest.count_total was set, its value is undefined otherwise | + - +### QueryInflationResponse +QueryInflationResponse is the response type for the Query/Inflation RPC +method. - - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `inflation` | [bytes](#bytes) | | inflation is the current minting inflation value. | - - -

      Top

      -## cosmos/authz/v1beta1/query.proto + +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. - -### QueryAuthorizationRequest -QueryAuthorizationRequest is the request type for the Query/Authorization RPC method. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `method_name` | [string](#string) | | | + +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines the parameters of the module. | - -### QueryAuthorizationResponse -QueryAuthorizationResponse is the response type for the Query/Authorization RPC method. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `authorization` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | | authorization is a authorization granted for grantee by granter. | + + + + - +### Query +Query provides defines the gRPC querier service. -### QueryAuthorizationsRequest -QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Params` | [QueryParamsRequest](#cosmos.mint.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.mint.v1beta1.QueryParamsResponse) | Params returns the total set of minting parameters. | GET|/cosmos/mint/v1beta1/params| +| `Inflation` | [QueryInflationRequest](#cosmos.mint.v1beta1.QueryInflationRequest) | [QueryInflationResponse](#cosmos.mint.v1beta1.QueryInflationResponse) | Inflation returns the current minting inflation value. | GET|/cosmos/mint/v1beta1/inflation| +| `AnnualProvisions` | [QueryAnnualProvisionsRequest](#cosmos.mint.v1beta1.QueryAnnualProvisionsRequest) | [QueryAnnualProvisionsResponse](#cosmos.mint.v1beta1.QueryAnnualProvisionsResponse) | AnnualProvisions current minting annual provisions value. | GET|/cosmos/mint/v1beta1/annual_provisions| + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | + +

      Top

      +## cosmos/mint/v1beta1/genesis.proto - + -### QueryAuthorizationsResponse -QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. +### GenesisState +GenesisState defines the mint module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorizations` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | repeated | authorizations is a list of grants granted for grantee by granter. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | +| `minter` | [Minter](#cosmos.mint.v1beta1.Minter) | | minter is a space for holding current inflation information. | +| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines all the paramaters of the module. | @@ -1555,140 +1631,151 @@ QueryAuthorizationsResponse is the response type for the Query/Authorizations RP - - - -### Query -Query defines the gRPC querier service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Authorization` | [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) | [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) | Returns any `Authorization` (or `nil`), with the expiration time, granted to the grantee by the granter for the provided msg type. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grant| -| `Authorizations` | [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) | [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) | Returns list of `Authorization`, granted to the grantee by the granter. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grants| - - +

      Top

      -## cosmos/bank/v1beta1/bank.proto +## cosmos/mint/v1beta1/mint.proto - + -### DenomUnit -DenomUnit represents a struct that describes a given -denomination unit of the basic token. +### Minter +Minter represents the minting state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | denom represents the string name of the given denom unit (e.g uatom). | -| `exponent` | [uint32](#uint32) | | exponent represents power of 10 exponent that one must raise the base_denom to in order to equal the given DenomUnit's denom 1 denom = 1^exponent base_denom (e.g. with a base_denom of uatom, one can create a DenomUnit of 'atom' with exponent = 6, thus: 1 atom = 10^6 uatom). | -| `aliases` | [string](#string) | repeated | aliases is a list of string aliases for the given denom | +| `inflation` | [string](#string) | | current annual inflation rate | +| `annual_provisions` | [string](#string) | | current annual expected provisions | - + -### Input -Input models transaction input. +### Params +Params holds parameters for the mint module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `mint_denom` | [string](#string) | | type of coin to mint | +| `inflation_rate_change` | [string](#string) | | maximum annual change in inflation rate | +| `inflation_max` | [string](#string) | | maximum inflation rate | +| `inflation_min` | [string](#string) | | minimum inflation rate | +| `goal_bonded` | [string](#string) | | goal of percent bonded atoms | +| `blocks_per_year` | [uint64](#uint64) | | expected blocks per year | + - + -### Metadata -Metadata represents a struct that describes -a basic token. + + + + + + + +

      Top

      + +## cosmos/feegrant/v1beta1/feegrant.proto + + + + + +### BasicFeeAllowance +BasicFeeAllowance implements FeeAllowance with a one-time grant of tokens +that optionally expires. The delegatee can use up to SpendLimit to cover fees. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `description` | [string](#string) | | | -| `denom_units` | [DenomUnit](#cosmos.bank.v1beta1.DenomUnit) | repeated | denom_units represents the list of DenomUnit's for a given coin | -| `base` | [string](#string) | | base represents the base denom (should be the DenomUnit with exponent = 0). | -| `display` | [string](#string) | | display indicates the suggested denom that should be displayed in clients. | +| `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `expiration` | [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) | | | - + -### Output -Output models transaction outputs. +### Duration +Duration is a span of a clock time or number of blocks. +This is designed to be added to an ExpiresAt struct. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `duration` | [google.protobuf.Duration](#google.protobuf.Duration) | | | +| `blocks` | [uint64](#uint64) | | | - + -### Params -Params defines the parameters for the bank module. +### ExpiresAt +ExpiresAt is a point in time where something expires. +It may be *either* block time or block height | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `send_enabled` | [SendEnabled](#cosmos.bank.v1beta1.SendEnabled) | repeated | | -| `default_send_enabled` | [bool](#bool) | | | +| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `height` | [int64](#int64) | | | - + -### SendEnabled -SendEnabled maps coin denom to a send_enabled status (whether a denom is -sendable). +### FeeAllowanceGrant +FeeAllowanceGrant is stored in the KVStore to record a grant with full context | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | | -| `enabled` | [bool](#bool) | | | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | - + -### Supply -Supply represents a struct that passively keeps track of the total supply -amounts in the network. +### PeriodicFeeAllowance +PeriodicFeeAllowance extends FeeAllowance to allow for both a maximum cap, +as well as a limit per time period. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `total` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `basic` | [BasicFeeAllowance](#cosmos.feegrant.v1beta1.BasicFeeAllowance) | | | +| `period` | [Duration](#cosmos.feegrant.v1beta1.Duration) | | | +| `period_spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `period_can_spend` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `period_reset` | [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) | | | @@ -1704,410 +1791,440 @@ amounts in the network. - +

      Top

      -## cosmos/bank/v1beta1/genesis.proto +## cosmos/feegrant/v1beta1/query.proto - + -### Balance -Balance defines an account address and balance pair used in the bank module's -genesis state. +### QueryFeeAllowanceRequest +QueryFeeAllowanceRequest is the request type for the Query/FeeAllowance RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the address of the balance holder. | -| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | coins defines the different coins this balance holds. | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | - + -### GenesisState -GenesisState defines the bank module's genesis state. +### QueryFeeAllowanceResponse +QueryFeeAllowanceResponse is the response type for the Query/FeeAllowance RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.bank.v1beta1.Params) | | params defines all the paramaters of the module. | -| `balances` | [Balance](#cosmos.bank.v1beta1.Balance) | repeated | balances is an array containing the balances of all the accounts. | -| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply represents the total supply. | -| `denom_metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | denom_metadata defines the metadata of the differents coins. | +| `fee_allowance` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | | fee_allowance is a fee_allowance granted for grantee by granter. | - - + - +### QueryFeeAllowancesRequest +QueryFeeAllowancesRequest is the request type for the Query/FeeAllowances RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `grantee` | [string](#string) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - -

      Top

      -## cosmos/bank/v1beta1/query.proto - + -### QueryAllBalancesRequest -QueryBalanceRequest is the request type for the Query/AllBalances RPC method. +### QueryFeeAllowancesResponse +QueryFeeAllowancesResponse is the response type for the Query/FeeAllowances RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the address to query balances for. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +| `fee_allowances` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | repeated | fee_allowances are fee_allowance's granted for grantee by granter. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | + - + -### QueryAllBalancesResponse -QueryAllBalancesResponse is the response type for the Query/AllBalances RPC -method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `balances` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | balances is the balances of all the coins. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | + + +### Query +Query defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `FeeAllowance` | [QueryFeeAllowanceRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowanceRequest) | [QueryFeeAllowanceResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowanceResponse) | FeeAllowance returns fee granted to the grantee by the granter. | GET|/cosmos/feegrant/v1beta1/fee_allowance/{granter}/{grantee}| +| `FeeAllowances` | [QueryFeeAllowancesRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowancesRequest) | [QueryFeeAllowancesResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowancesResponse) | FeeAllowances returns all the grants for address. | GET|/cosmos/feegrant/v1beta1/fee_allowances/{grantee}| + + + +

      Top

      +## cosmos/feegrant/v1beta1/tx.proto - -### QueryBalanceRequest -QueryBalanceRequest is the request type for the Query/Balance RPC method. + + +### MsgGrantFeeAllowance +MsgGrantFeeAllowance adds permission for Grantee to spend up to Allowance +of fees from the account of Granter. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the address to query balances for. | -| `denom` | [string](#string) | | denom is the coin denom to query balances for. | - - +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | - -### QueryBalanceResponse -QueryBalanceResponse is the response type for the Query/Balance RPC method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | balance is the balance of the coin. | +### MsgGrantFeeAllowanceResponse +MsgGrantFeeAllowanceResponse defines the Msg/GrantFeeAllowanceResponse response type. - + -### QueryDenomMetadataRequest -QueryDenomMetadataRequest is the request type for the Query/DenomMetadata RPC method. +### MsgRevokeFeeAllowance +MsgRevokeFeeAllowance removes any existing FeeAllowance from Granter to Grantee. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | denom is the coin denom to query the metadata for. | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | - + + +### MsgRevokeFeeAllowanceResponse +MsgRevokeFeeAllowanceResponse defines the Msg/RevokeFeeAllowanceResponse response type. + -### QueryDenomMetadataResponse -QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC -method. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | | metadata describes and provides all the client information for the requested token. | + + + + - +### Msg +Msg defines the feegrant msg service. -### QueryDenomsMetadataRequest -QueryDenomsMetadataRequest is the request type for the Query/DenomsMetadata RPC method. +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `GrantFeeAllowance` | [MsgGrantFeeAllowance](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowance) | [MsgGrantFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowanceResponse) | GrantFeeAllowance grants fee allowance to the grantee on the granter's account with the provided expiration time. | | +| `RevokeFeeAllowance` | [MsgRevokeFeeAllowance](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowance) | [MsgRevokeFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowanceResponse) | RevokeFeeAllowance revokes any fee allowance of granter's account that has been granted to the grantee. | | + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + +

      Top

      +## cosmos/feegrant/v1beta1/genesis.proto - + -### QueryDenomsMetadataResponse -QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata RPC -method. +### GenesisState +GenesisState contains a set of fee allowances, persisted from the store | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `metadatas` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | metadata provides the client information for all the registered tokens. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| `fee_allowances` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | repeated | | + - + -### QueryParamsRequest -QueryParamsRequest defines the request type for querying x/bank parameters. + + + +

      Top

      +## cosmos/capability/v1beta1/capability.proto - -### QueryParamsResponse -QueryParamsResponse defines the response type for querying x/bank parameters. + + + +### Capability +Capability defines an implementation of an object capability. The index +provided to a Capability must be globally unique. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.bank.v1beta1.Params) | | | +| `index` | [uint64](#uint64) | | | - + -### QuerySupplyOfRequest -QuerySupplyOfRequest is the request type for the Query/SupplyOf RPC method. +### CapabilityOwners +CapabilityOwners defines a set of owners of a single Capability. The set of +owners must be unique. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | denom is the coin denom to query balances for. | +| `owners` | [Owner](#cosmos.capability.v1beta1.Owner) | repeated | | - + -### QuerySupplyOfResponse -QuerySupplyOfResponse is the response type for the Query/SupplyOf RPC method. +### Owner +Owner defines a single capability owner. An owner is defined by the name of +capability and the module name. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | amount is the supply of the coin. | +| `module` | [string](#string) | | | +| `name` | [string](#string) | | | + - + -### QueryTotalSupplyRequest -QueryTotalSupplyRequest is the request type for the Query/TotalSupply RPC -method. + + + + +

      Top

      + +## cosmos/capability/v1beta1/genesis.proto - + -### QueryTotalSupplyResponse -QueryTotalSupplyResponse is the response type for the Query/TotalSupply RPC -method +### GenesisOwners +GenesisOwners defines the capability owners with their corresponding index. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply is the supply of the coins | +| `index` | [uint64](#uint64) | | index is the index of the capability owner. | +| `index_owners` | [CapabilityOwners](#cosmos.capability.v1beta1.CapabilityOwners) | | index_owners are the owners at the given index. | - - + - +### GenesisState +GenesisState defines the capability module's genesis state. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `index` | [uint64](#uint64) | | index is the capability global index. | +| `owners` | [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) | repeated | owners represents a map from index to owners of the capability index index key is string to allow amino marshalling. | -### Query -Query defines the gRPC querier service. -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Balance` | [QueryBalanceRequest](#cosmos.bank.v1beta1.QueryBalanceRequest) | [QueryBalanceResponse](#cosmos.bank.v1beta1.QueryBalanceResponse) | Balance queries the balance of a single coin for a single account. | GET|/cosmos/bank/v1beta1/balances/{address}/{denom}| -| `AllBalances` | [QueryAllBalancesRequest](#cosmos.bank.v1beta1.QueryAllBalancesRequest) | [QueryAllBalancesResponse](#cosmos.bank.v1beta1.QueryAllBalancesResponse) | AllBalances queries the balance of all coins for a single account. | GET|/cosmos/bank/v1beta1/balances/{address}| -| `TotalSupply` | [QueryTotalSupplyRequest](#cosmos.bank.v1beta1.QueryTotalSupplyRequest) | [QueryTotalSupplyResponse](#cosmos.bank.v1beta1.QueryTotalSupplyResponse) | TotalSupply queries the total supply of all coins. | GET|/cosmos/bank/v1beta1/supply| -| `SupplyOf` | [QuerySupplyOfRequest](#cosmos.bank.v1beta1.QuerySupplyOfRequest) | [QuerySupplyOfResponse](#cosmos.bank.v1beta1.QuerySupplyOfResponse) | SupplyOf queries the supply of a single coin. | GET|/cosmos/bank/v1beta1/supply/{denom}| -| `Params` | [QueryParamsRequest](#cosmos.bank.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.bank.v1beta1.QueryParamsResponse) | Params queries the parameters of x/bank module. | GET|/cosmos/bank/v1beta1/params| -| `DenomMetadata` | [QueryDenomMetadataRequest](#cosmos.bank.v1beta1.QueryDenomMetadataRequest) | [QueryDenomMetadataResponse](#cosmos.bank.v1beta1.QueryDenomMetadataResponse) | DenomsMetadata queries the client metadata of a given coin denomination. | GET|/cosmos/bank/v1beta1/denoms_metadata/{denom}| -| `DenomsMetadata` | [QueryDenomsMetadataRequest](#cosmos.bank.v1beta1.QueryDenomsMetadataRequest) | [QueryDenomsMetadataResponse](#cosmos.bank.v1beta1.QueryDenomsMetadataResponse) | DenomsMetadata queries the client metadata for all registered coin denominations. | GET|/cosmos/bank/v1beta1/denoms_metadata| + + + + + + + + - +

      Top

      -## cosmos/bank/v1beta1/tx.proto +## cosmos/bank/v1beta1/bank.proto - + -### MsgMultiSend -MsgMultiSend represents an arbitrary multi-in, multi-out send message. +### DenomUnit +DenomUnit represents a struct that describes a given +denomination unit of the basic token. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `inputs` | [Input](#cosmos.bank.v1beta1.Input) | repeated | | -| `outputs` | [Output](#cosmos.bank.v1beta1.Output) | repeated | | +| `denom` | [string](#string) | | denom represents the string name of the given denom unit (e.g uatom). | +| `exponent` | [uint32](#uint32) | | exponent represents power of 10 exponent that one must raise the base_denom to in order to equal the given DenomUnit's denom 1 denom = 1^exponent base_denom (e.g. with a base_denom of uatom, one can create a DenomUnit of 'atom' with exponent = 6, thus: 1 atom = 10^6 uatom). | +| `aliases` | [string](#string) | repeated | aliases is a list of string aliases for the given denom | - + -### MsgMultiSendResponse -MsgMultiSendResponse defines the Msg/MultiSend response type. +### Input +Input models transaction input. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | | +| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - -### MsgSend -MsgSend represents a message to send coins from one account to another. + + + +### Metadata +Metadata represents a struct that describes +a basic token. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `from_address` | [string](#string) | | | -| `to_address` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - - +| `description` | [string](#string) | | | +| `denom_units` | [DenomUnit](#cosmos.bank.v1beta1.DenomUnit) | repeated | denom_units represents the list of DenomUnit's for a given coin | +| `base` | [string](#string) | | base represents the base denom (should be the DenomUnit with exponent = 0). | +| `display` | [string](#string) | | display indicates the suggested denom that should be displayed in clients. | - -### MsgSendResponse -MsgSendResponse defines the Msg/Send response type. + +### Output +Output models transaction outputs. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | | +| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - - - - -### Msg -Msg defines the bank Msg service. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Send` | [MsgSend](#cosmos.bank.v1beta1.MsgSend) | [MsgSendResponse](#cosmos.bank.v1beta1.MsgSendResponse) | Send defines a method for sending coins from one account to another account. | | -| `MultiSend` | [MsgMultiSend](#cosmos.bank.v1beta1.MsgMultiSend) | [MsgMultiSendResponse](#cosmos.bank.v1beta1.MsgMultiSendResponse) | MultiSend defines a method for sending coins from some accounts to other accounts. | | +### Params +Params defines the parameters for the bank module. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `send_enabled` | [SendEnabled](#cosmos.bank.v1beta1.SendEnabled) | repeated | | +| `default_send_enabled` | [bool](#bool) | | | - -

      Top

      -## cosmos/base/kv/v1beta1/kv.proto - + -### Pair -Pair defines a key/value bytes tuple. +### SendEnabled +SendEnabled maps coin denom to a send_enabled status (whether a denom is +sendable). | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | -| `value` | [bytes](#bytes) | | | +| `denom` | [string](#string) | | | +| `enabled` | [bool](#bool) | | | - + -### Pairs -Pairs defines a repeated slice of Pair objects. +### Supply +Supply represents a struct that passively keeps track of the total supply +amounts in the network. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pairs` | [Pair](#cosmos.base.kv.v1beta1.Pair) | repeated | | +| `total` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | @@ -2123,257 +2240,216 @@ Pairs defines a repeated slice of Pair objects. - +

      Top

      -## cosmos/base/reflection/v1beta1/reflection.proto - - - - - -### ListAllInterfacesRequest -ListAllInterfacesRequest is the request type of the ListAllInterfaces RPC. - - - +## cosmos/bank/v1beta1/query.proto - + -### ListAllInterfacesResponse -ListAllInterfacesResponse is the response type of the ListAllInterfaces RPC. +### QueryAllBalancesRequest +QueryBalanceRequest is the request type for the Query/AllBalances RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `interface_names` | [string](#string) | repeated | interface_names is an array of all the registered interfaces. | +| `address` | [string](#string) | | address is the address to query balances for. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - + -### ListImplementationsRequest -ListImplementationsRequest is the request type of the ListImplementations -RPC. +### QueryAllBalancesResponse +QueryAllBalancesResponse is the response type for the Query/AllBalances RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `interface_name` | [string](#string) | | interface_name defines the interface to query the implementations for. | +| `balances` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | balances is the balances of all the coins. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - + -### ListImplementationsResponse -ListImplementationsResponse is the response type of the ListImplementations -RPC. +### QueryBalanceRequest +QueryBalanceRequest is the request type for the Query/Balance RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `implementation_message_names` | [string](#string) | repeated | | - - - - +| `address` | [string](#string) | | address is the address to query balances for. | +| `denom` | [string](#string) | | denom is the coin denom to query balances for. | - - - - -### ReflectionService -ReflectionService defines a service for interface reflection. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `ListAllInterfaces` | [ListAllInterfacesRequest](#cosmos.base.reflection.v1beta1.ListAllInterfacesRequest) | [ListAllInterfacesResponse](#cosmos.base.reflection.v1beta1.ListAllInterfacesResponse) | ListAllInterfaces lists all the interfaces registered in the interface registry. | GET|/cosmos/base/reflection/v1beta1/interfaces| -| `ListImplementations` | [ListImplementationsRequest](#cosmos.base.reflection.v1beta1.ListImplementationsRequest) | [ListImplementationsResponse](#cosmos.base.reflection.v1beta1.ListImplementationsResponse) | ListImplementations list all the concrete types that implement a given interface. | GET|/cosmos/base/reflection/v1beta1/interfaces/{interface_name}/implementations| +### QueryBalanceResponse +QueryBalanceResponse is the response type for the Query/Balance RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | balance is the balance of the coin. | - -

      Top

      -## cosmos/base/snapshots/v1beta1/snapshot.proto - + -### Metadata -Metadata contains SDK-specific snapshot metadata. +### QueryDenomMetadataRequest +QueryDenomMetadataRequest is the request type for the Query/DenomMetadata RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `chunk_hashes` | [bytes](#bytes) | repeated | SHA-256 chunk hashes | +| `denom` | [string](#string) | | denom is the coin denom to query the metadata for. | - + -### Snapshot -Snapshot contains Tendermint state sync snapshot info. +### QueryDenomMetadataResponse +QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [uint64](#uint64) | | | -| `format` | [uint32](#uint32) | | | -| `chunks` | [uint32](#uint32) | | | -| `hash` | [bytes](#bytes) | | | -| `metadata` | [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) | | | +| `metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | | metadata describes and provides all the client information for the requested token. | - - + - +### QueryDenomsMetadataRequest +QueryDenomsMetadataRequest is the request type for the Query/DenomsMetadata RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - -

      Top

      -## cosmos/base/store/v1beta1/commit_info.proto - + -### CommitID -CommitID defines the committment information when a specific store is -committed. +### QueryDenomsMetadataResponse +QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `version` | [int64](#int64) | | | -| `hash` | [bytes](#bytes) | | | - - +| `metadatas` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | metadata provides the client information for all the registered tokens. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - -### CommitInfo -CommitInfo defines commit information used by the multi-store when committing -a version/height. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `version` | [int64](#int64) | | | -| `store_infos` | [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) | repeated | | +### QueryParamsRequest +QueryParamsRequest defines the request type for querying x/bank parameters. - + -### StoreInfo -StoreInfo defines store-specific commit information. It contains a reference -between a store name and the commit ID. +### QueryParamsResponse +QueryParamsResponse defines the response type for querying x/bank parameters. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | | -| `commit_id` | [CommitID](#cosmos.base.store.v1beta1.CommitID) | | | +| `params` | [Params](#cosmos.bank.v1beta1.Params) | | | - - + - +### QuerySupplyOfRequest +QuerySupplyOfRequest is the request type for the Query/SupplyOf RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `denom` | [string](#string) | | denom is the coin denom to query balances for. | - -

      Top

      -## cosmos/base/store/v1beta1/snapshot.proto - + -### SnapshotIAVLItem -SnapshotIAVLItem is an exported IAVL node. +### QuerySupplyOfResponse +QuerySupplyOfResponse is the response type for the Query/SupplyOf RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | -| `value` | [bytes](#bytes) | | | -| `version` | [int64](#int64) | | | -| `height` | [int32](#int32) | | | - - +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | amount is the supply of the coin. | - -### SnapshotItem -SnapshotItem is an item contained in a rootmulti.Store snapshot. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `store` | [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) | | | -| `iavl` | [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) | | | +### QueryTotalSupplyRequest +QueryTotalSupplyRequest is the request type for the Query/TotalSupply RPC +method. - + -### SnapshotStoreItem -SnapshotStoreItem contains metadata about a snapshotted store. +### QueryTotalSupplyResponse +QueryTotalSupplyResponse is the response type for the Query/TotalSupply RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | | +| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply is the supply of the coins | @@ -2385,240 +2461,288 @@ SnapshotStoreItem contains metadata about a snapshotted store. + + + +### Query +Query defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Balance` | [QueryBalanceRequest](#cosmos.bank.v1beta1.QueryBalanceRequest) | [QueryBalanceResponse](#cosmos.bank.v1beta1.QueryBalanceResponse) | Balance queries the balance of a single coin for a single account. | GET|/cosmos/bank/v1beta1/balances/{address}/{denom}| +| `AllBalances` | [QueryAllBalancesRequest](#cosmos.bank.v1beta1.QueryAllBalancesRequest) | [QueryAllBalancesResponse](#cosmos.bank.v1beta1.QueryAllBalancesResponse) | AllBalances queries the balance of all coins for a single account. | GET|/cosmos/bank/v1beta1/balances/{address}| +| `TotalSupply` | [QueryTotalSupplyRequest](#cosmos.bank.v1beta1.QueryTotalSupplyRequest) | [QueryTotalSupplyResponse](#cosmos.bank.v1beta1.QueryTotalSupplyResponse) | TotalSupply queries the total supply of all coins. | GET|/cosmos/bank/v1beta1/supply| +| `SupplyOf` | [QuerySupplyOfRequest](#cosmos.bank.v1beta1.QuerySupplyOfRequest) | [QuerySupplyOfResponse](#cosmos.bank.v1beta1.QuerySupplyOfResponse) | SupplyOf queries the supply of a single coin. | GET|/cosmos/bank/v1beta1/supply/{denom}| +| `Params` | [QueryParamsRequest](#cosmos.bank.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.bank.v1beta1.QueryParamsResponse) | Params queries the parameters of x/bank module. | GET|/cosmos/bank/v1beta1/params| +| `DenomMetadata` | [QueryDenomMetadataRequest](#cosmos.bank.v1beta1.QueryDenomMetadataRequest) | [QueryDenomMetadataResponse](#cosmos.bank.v1beta1.QueryDenomMetadataResponse) | DenomsMetadata queries the client metadata of a given coin denomination. | GET|/cosmos/bank/v1beta1/denoms_metadata/{denom}| +| `DenomsMetadata` | [QueryDenomsMetadataRequest](#cosmos.bank.v1beta1.QueryDenomsMetadataRequest) | [QueryDenomsMetadataResponse](#cosmos.bank.v1beta1.QueryDenomsMetadataResponse) | DenomsMetadata queries the client metadata for all registered coin denominations. | GET|/cosmos/bank/v1beta1/denoms_metadata| + - +

      Top

      -## cosmos/base/tendermint/v1beta1/query.proto +## cosmos/bank/v1beta1/tx.proto - + -### GetBlockByHeightRequest -GetBlockByHeightRequest is the request type for the Query/GetBlockByHeight RPC method. +### MsgMultiSend +MsgMultiSend represents an arbitrary multi-in, multi-out send message. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | | +| `inputs` | [Input](#cosmos.bank.v1beta1.Input) | repeated | | +| `outputs` | [Output](#cosmos.bank.v1beta1.Output) | repeated | | - + + +### MsgMultiSendResponse +MsgMultiSendResponse defines the Msg/MultiSend response type. + + + + -### GetBlockByHeightResponse -GetBlockByHeightResponse is the response type for the Query/GetBlockByHeight RPC method. + + + +### MsgSend +MsgSend represents a message to send coins from one account to another. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | -| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | +| `from_address` | [string](#string) | | | +| `to_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - + -### GetLatestBlockRequest -GetLatestBlockRequest is the request type for the Query/GetLatestBlock RPC method. +### MsgSendResponse +MsgSendResponse defines the Msg/Send response type. + - + -### GetLatestBlockResponse -GetLatestBlockResponse is the response type for the Query/GetLatestBlock RPC method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | -| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | + + +### Msg +Msg defines the bank Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Send` | [MsgSend](#cosmos.bank.v1beta1.MsgSend) | [MsgSendResponse](#cosmos.bank.v1beta1.MsgSendResponse) | Send defines a method for sending coins from one account to another account. | | +| `MultiSend` | [MsgMultiSend](#cosmos.bank.v1beta1.MsgMultiSend) | [MsgMultiSendResponse](#cosmos.bank.v1beta1.MsgMultiSendResponse) | MultiSend defines a method for sending coins from some accounts to other accounts. | | + + +

      Top

      +## cosmos/bank/v1beta1/genesis.proto - -### GetLatestValidatorSetRequest -GetLatestValidatorSetRequest is the request type for the Query/GetValidatorSetByHeight RPC method. + + + +### Balance +Balance defines an account address and balance pair used in the bank module's +genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | +| `address` | [string](#string) | | address is the address of the balance holder. | +| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | coins defines the different coins this balance holds. | - + -### GetLatestValidatorSetResponse -GetLatestValidatorSetResponse is the response type for the Query/GetValidatorSetByHeight RPC method. +### GenesisState +GenesisState defines the bank module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `block_height` | [int64](#int64) | | | -| `validators` | [Validator](#cosmos.base.tendermint.v1beta1.Validator) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | +| `params` | [Params](#cosmos.bank.v1beta1.Params) | | params defines all the paramaters of the module. | +| `balances` | [Balance](#cosmos.bank.v1beta1.Balance) | repeated | balances is an array containing the balances of all the accounts. | +| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply represents the total supply. | +| `denom_metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | denom_metadata defines the metadata of the differents coins. | + - + -### GetNodeInfoRequest -GetNodeInfoRequest is the request type for the Query/GetNodeInfo RPC method. + + + + +

      Top

      +## cosmos/authz/v1beta1/authz.proto - -### GetNodeInfoResponse -GetNodeInfoResponse is the request type for the Query/GetNodeInfo RPC method. + + +### AuthorizationGrant +AuthorizationGrant gives permissions to execute +the provide method with expiration time. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `default_node_info` | [tendermint.p2p.DefaultNodeInfo](#tendermint.p2p.DefaultNodeInfo) | | | -| `application_version` | [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) | | | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - + -### GetSyncingRequest -GetSyncingRequest is the request type for the Query/GetSyncing RPC method. +### GenericAuthorization +GenericAuthorization gives the grantee unrestricted permissions to execute +the provided method on behalf of the granter's account. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `method_name` | [string](#string) | | method name to grant unrestricted permissions to execute Note: MethodName() is already a method on `GenericAuthorization` type, we need some custom naming here so using `MessageName` | - + -### GetSyncingResponse -GetSyncingResponse is the response type for the Query/GetSyncing RPC method. +### SendAuthorization +SendAuthorization allows the grantee to spend up to spend_limit coins from +the granter's account. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `syncing` | [bool](#bool) | | | +| `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | + - + -### GetValidatorSetByHeightRequest -GetValidatorSetByHeightRequest is the request type for the Query/GetValidatorSetByHeight RPC method. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | + +

      Top

      +## cosmos/authz/v1beta1/query.proto - + -### GetValidatorSetByHeightResponse -GetValidatorSetByHeightResponse is the response type for the Query/GetValidatorSetByHeight RPC method. +### QueryAuthorizationRequest +QueryAuthorizationRequest is the request type for the Query/Authorization RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `block_height` | [int64](#int64) | | | -| `validators` | [Validator](#cosmos.base.tendermint.v1beta1.Validator) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `method_name` | [string](#string) | | | - + -### Module -Module is the type for VersionInfo +### QueryAuthorizationResponse +QueryAuthorizationResponse is the response type for the Query/Authorization RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [string](#string) | | module path | -| `version` | [string](#string) | | module version | -| `sum` | [string](#string) | | checksum | +| `authorization` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | | authorization is a authorization granted for grantee by granter. | - + -### Validator -Validator is the type for the validator-set. +### QueryAuthorizationsRequest +QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `voting_power` | [int64](#int64) | | | -| `proposer_priority` | [int64](#int64) | | | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - + -### VersionInfo -VersionInfo is the type for the GetNodeInfoResponse message. +### QueryAuthorizationsResponse +QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | | -| `app_name` | [string](#string) | | | -| `version` | [string](#string) | | | -| `git_commit` | [string](#string) | | | -| `build_tags` | [string](#string) | | | -| `go_version` | [string](#string) | | | -| `build_deps` | [Module](#cosmos.base.tendermint.v1beta1.Module) | repeated | | +| `authorizations` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | repeated | authorizations is a list of grants granted for grantee by granter. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | @@ -2631,122 +2755,111 @@ VersionInfo is the type for the GetNodeInfoResponse message. - + -### Service -Service defines the gRPC querier service for tendermint queries. +### Query +Query defines the gRPC querier service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `GetNodeInfo` | [GetNodeInfoRequest](#cosmos.base.tendermint.v1beta1.GetNodeInfoRequest) | [GetNodeInfoResponse](#cosmos.base.tendermint.v1beta1.GetNodeInfoResponse) | GetNodeInfo queries the current node info. | GET|/cosmos/base/tendermint/v1beta1/node_info| -| `GetSyncing` | [GetSyncingRequest](#cosmos.base.tendermint.v1beta1.GetSyncingRequest) | [GetSyncingResponse](#cosmos.base.tendermint.v1beta1.GetSyncingResponse) | GetSyncing queries node syncing. | GET|/cosmos/base/tendermint/v1beta1/syncing| -| `GetLatestBlock` | [GetLatestBlockRequest](#cosmos.base.tendermint.v1beta1.GetLatestBlockRequest) | [GetLatestBlockResponse](#cosmos.base.tendermint.v1beta1.GetLatestBlockResponse) | GetLatestBlock returns the latest block. | GET|/cosmos/base/tendermint/v1beta1/blocks/latest| -| `GetBlockByHeight` | [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) | [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) | GetBlockByHeight queries block for given height. | GET|/cosmos/base/tendermint/v1beta1/blocks/{height}| -| `GetLatestValidatorSet` | [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) | [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) | GetLatestValidatorSet queries latest validator-set. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/latest| -| `GetValidatorSetByHeight` | [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) | [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) | GetValidatorSetByHeight queries validator-set at a given height. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/{height}| +| `Authorization` | [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) | [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) | Returns any `Authorization` (or `nil`), with the expiration time, granted to the grantee by the granter for the provided msg type. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grant| +| `Authorizations` | [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) | [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) | Returns list of `Authorization`, granted to the grantee by the granter. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grants| - +

      Top

      -## cosmos/capability/v1beta1/capability.proto +## cosmos/authz/v1beta1/tx.proto - + -### Capability -Capability defines an implementation of an object capability. The index -provided to a Capability must be globally unique. +### MsgExecAuthorizedRequest +MsgExecAuthorizedRequest attempts to execute the provided messages using +authorizations granted to the grantee. Each message should have only +one signer corresponding to the granter of the authorization. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `index` | [uint64](#uint64) | | | +| `grantee` | [string](#string) | | | +| `msgs` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | - + -### CapabilityOwners -CapabilityOwners defines a set of owners of a single Capability. The set of -owners must be unique. +### MsgExecAuthorizedResponse +MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse response type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `owners` | [Owner](#cosmos.capability.v1beta1.Owner) | repeated | | +| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | | - + -### Owner -Owner defines a single capability owner. An owner is defined by the name of -capability and the module name. +### MsgGrantAuthorizationRequest +MsgGrantAuthorizationRequest grants the provided authorization to the grantee on the granter's +account with the provided expiration time. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `module` | [string](#string) | | | -| `name` | [string](#string) | | | - - +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - - - - + +### MsgGrantAuthorizationResponse +MsgGrantAuthorizationResponse defines the Msg/MsgGrantAuthorization response type. - -

      Top

      -## cosmos/capability/v1beta1/genesis.proto - + -### GenesisOwners -GenesisOwners defines the capability owners with their corresponding index. +### MsgRevokeAuthorizationRequest +MsgRevokeAuthorizationRequest revokes any authorization with the provided sdk.Msg type on the +granter's account with that has been granted to the grantee. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `index` | [uint64](#uint64) | | index is the index of the capability owner. | -| `index_owners` | [CapabilityOwners](#cosmos.capability.v1beta1.CapabilityOwners) | | index_owners are the owners at the given index. | - - +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `method_name` | [string](#string) | | | - -### GenesisState -GenesisState defines the capability module's genesis state. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `index` | [uint64](#uint64) | | index is the capability global index. | -| `owners` | [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) | repeated | owners represents a map from index to owners of the capability index index key is string to allow amino marshalling. | +### MsgRevokeAuthorizationResponse +MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse response type. @@ -2758,221 +2871,251 @@ GenesisState defines the capability module's genesis state. + + + +### Msg +Msg defines the authz Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `GrantAuthorization` | [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) | [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) | GrantAuthorization grants the provided authorization to the grantee on the granter's account with the provided expiration time. | | +| `ExecAuthorized` | [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) | [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) | ExecAuthorized attempts to execute the provided messages using authorizations granted to the grantee. Each message should have only one signer corresponding to the granter of the authorization. | | +| `RevokeAuthorization` | [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) | [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) | RevokeAuthorization revokes any authorization corresponding to the provided method name on the granter's account that has been granted to the grantee. | | + - +

      Top

      -## cosmos/crisis/v1beta1/genesis.proto +## cosmos/authz/v1beta1/genesis.proto - + ### GenesisState -GenesisState defines the crisis module's genesis state. +GenesisState defines the authz module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `constant_fee` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | constant_fee is the fee used to verify the invariant in the crisis module. | - - +| `authorization` | [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) | repeated | | - - - - + +### GrantAuthorization +GrantAuthorization defines the GenesisState/GrantAuthorization type. - -

      Top

      +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -## cosmos/crisis/v1beta1/tx.proto - -### MsgVerifyInvariant -MsgVerifyInvariant represents a message to verify a particular invariance. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `sender` | [string](#string) | | | -| `invariant_module_name` | [string](#string) | | | -| `invariant_route` | [string](#string) | | | + + + +

      Top

      +## cosmos/gov/v1beta1/gov.proto - -### MsgVerifyInvariantResponse -MsgVerifyInvariantResponse defines the Msg/VerifyInvariant response type. + +### Deposit +Deposit defines an amount deposited by an account address to an active +proposal. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | | +| `depositor` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - - - - -### Msg -Msg defines the bank Msg service. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `VerifyInvariant` | [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) | [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) | VerifyInvariant defines a method to verify a particular invariance. | | +### DepositParams +DepositParams defines the params for deposits on governance proposals. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `min_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | Minimum deposit for a proposal to enter voting period. | +| `max_deposit_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months. | - -

      Top

      -## cosmos/crypto/ed25519/keys.proto - + -### PrivKey -PrivKey defines a ed25519 private key. +### Proposal +Proposal defines the core field members of a governance proposal. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | +| `proposal_id` | [uint64](#uint64) | | | +| `content` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `status` | [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) | | | +| `final_tally_result` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | | +| `submit_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `deposit_end_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `total_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `voting_start_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `voting_end_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - + -### PubKey -PubKey defines a ed25519 public key -Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte -if the y-coordinate is the lexicographically largest of the two associated with -the x-coordinate. Otherwise the first byte is a 0x03. -This prefix is followed with the x-coordinate. +### TallyParams +TallyParams defines the params for tallying votes on governance proposals. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | +| `quorum` | [bytes](#bytes) | | Minimum percentage of total stake needed to vote for a result to be considered valid. | +| `threshold` | [bytes](#bytes) | | Minimum proportion of Yes votes for proposal to pass. Default value: 0.5. | +| `veto_threshold` | [bytes](#bytes) | | Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Default value: 1/3. | - - + - +### TallyResult +TallyResult defines a standard tally for a governance proposal. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `yes` | [string](#string) | | | +| `abstain` | [string](#string) | | | +| `no` | [string](#string) | | | +| `no_with_veto` | [string](#string) | | | - -

      Top

      -## cosmos/crypto/multisig/keys.proto - + -### LegacyAminoPubKey -LegacyAminoPubKey specifies a public key type -which nests multiple public keys and a threshold, -it uses legacy amino address rules. +### TextProposal +TextProposal defines a standard text proposal whose changes need to be +manually updated in case of approval. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `threshold` | [uint32](#uint32) | | | -| `public_keys` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | - - + - +### Vote +Vote defines a vote on a governance proposal. +A Vote consists of a proposal ID, the voter, and the vote option. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | | +| `voter` | [string](#string) | | | +| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | - -

      Top

      -## cosmos/crypto/multisig/v1beta1/multisig.proto - + -### CompactBitArray -CompactBitArray is an implementation of a space efficient bit array. -This is used to ensure that the encoded data takes up a minimal amount of -space after proto encoding. -This is not thread safe, and is not intended for concurrent usage. +### VotingParams +VotingParams defines the params for voting on governance proposals. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `extra_bits_stored` | [uint32](#uint32) | | | -| `elems` | [bytes](#bytes) | | | +| `voting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Length of the voting period. | + - -### MultiSignature -MultiSignature wraps the signatures from a multisig.LegacyAminoPubKey. -See cosmos.tx.v1betata1.ModeInfo.Multi for how to specify which signers -signed and with which modes. + +### ProposalStatus +ProposalStatus enumerates the valid statuses of a proposal. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `signatures` | [bytes](#bytes) | repeated | | +| Name | Number | Description | +| ---- | ------ | ----------- | +| PROPOSAL_STATUS_UNSPECIFIED | 0 | PROPOSAL_STATUS_UNSPECIFIED defines the default propopsal status. | +| PROPOSAL_STATUS_DEPOSIT_PERIOD | 1 | PROPOSAL_STATUS_DEPOSIT_PERIOD defines a proposal status during the deposit period. | +| PROPOSAL_STATUS_VOTING_PERIOD | 2 | PROPOSAL_STATUS_VOTING_PERIOD defines a proposal status during the voting period. | +| PROPOSAL_STATUS_PASSED | 3 | PROPOSAL_STATUS_PASSED defines a proposal status of a proposal that has passed. | +| PROPOSAL_STATUS_REJECTED | 4 | PROPOSAL_STATUS_REJECTED defines a proposal status of a proposal that has been rejected. | +| PROPOSAL_STATUS_FAILED | 5 | PROPOSAL_STATUS_FAILED defines a proposal status of a proposal that has failed. | + +### VoteOption +VoteOption enumerates the valid vote options for a given governance proposal. + +| Name | Number | Description | +| ---- | ------ | ----------- | +| VOTE_OPTION_UNSPECIFIED | 0 | VOTE_OPTION_UNSPECIFIED defines a no-op vote option. | +| VOTE_OPTION_YES | 1 | VOTE_OPTION_YES defines a yes vote option. | +| VOTE_OPTION_ABSTAIN | 2 | VOTE_OPTION_ABSTAIN defines an abstain vote option. | +| VOTE_OPTION_NO | 3 | VOTE_OPTION_NO defines a no vote option. | +| VOTE_OPTION_NO_WITH_VETO | 4 | VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. | - @@ -2982,280 +3125,260 @@ signed and with which modes. - +

      Top

      -## cosmos/crypto/secp256k1/keys.proto +## cosmos/gov/v1beta1/query.proto - + -### PrivKey -PrivKey defines a secp256k1 private key. +### QueryDepositRequest +QueryDepositRequest is the request type for the Query/Deposit RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `depositor` | [string](#string) | | depositor defines the deposit addresses from the proposals. | - + -### PubKey -PubKey defines a secp256k1 public key -Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte -if the y-coordinate is the lexicographically largest of the two associated with -the x-coordinate. Otherwise the first byte is a 0x03. -This prefix is followed with the x-coordinate. +### QueryDepositResponse +QueryDepositResponse is the response type for the Query/Deposit RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | +| `deposit` | [Deposit](#cosmos.gov.v1beta1.Deposit) | | deposit defines the requested deposit. | - - + - +### QueryDepositsRequest +QueryDepositsRequest is the request type for the Query/Deposits RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - -

      Top

      -## cosmos/distribution/v1beta1/distribution.proto - + -### CommunityPoolSpendProposal -CommunityPoolSpendProposal details a proposal for use of community funds, -together with how many coins are proposed to be spent, and to which -recipient account. +### QueryDepositsResponse +QueryDepositsResponse is the response type for the Query/Deposits RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `recipient` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `deposits` | [Deposit](#cosmos.gov.v1beta1.Deposit) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - + -### CommunityPoolSpendProposalWithDeposit -CommunityPoolSpendProposalWithDeposit defines a CommunityPoolSpendProposal -with a deposit +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `recipient` | [string](#string) | | | -| `amount` | [string](#string) | | | -| `deposit` | [string](#string) | | | +| `params_type` | [string](#string) | | params_type defines which parameters to query for, can be one of "voting", "tallying" or "deposit". | - + -### DelegationDelegatorReward -DelegationDelegatorReward represents the properties -of a delegator's delegation reward. +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | | -| `reward` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `voting_params` | [VotingParams](#cosmos.gov.v1beta1.VotingParams) | | voting_params defines the parameters related to voting. | +| `deposit_params` | [DepositParams](#cosmos.gov.v1beta1.DepositParams) | | deposit_params defines the parameters related to deposit. | +| `tally_params` | [TallyParams](#cosmos.gov.v1beta1.TallyParams) | | tally_params defines the parameters related to tally. | + + + + + + + + +### QueryProposalRequest +QueryProposalRequest is the request type for the Query/Proposal RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | - + -### DelegatorStartingInfo -DelegatorStartingInfo represents the starting info for a delegator reward -period. It tracks the previous validator period, the delegation's amount of -staking token, and the creation height (to check later on if any slashes have -occurred). NOTE: Even though validators are slashed to whole staking tokens, -the delegators within the validator may be left with less than a full token, -thus sdk.Dec is used. +### QueryProposalResponse +QueryProposalResponse is the response type for the Query/Proposal RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `previous_period` | [uint64](#uint64) | | | -| `stake` | [string](#string) | | | -| `height` | [uint64](#uint64) | | | +| `proposal` | [Proposal](#cosmos.gov.v1beta1.Proposal) | | | - + -### FeePool -FeePool is the global fee pool for distribution. +### QueryProposalsRequest +QueryProposalsRequest is the request type for the Query/Proposals RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `community_pool` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `proposal_status` | [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) | | proposal_status defines the status of the proposals. | +| `voter` | [string](#string) | | voter defines the voter address for the proposals. | +| `depositor` | [string](#string) | | depositor defines the deposit addresses from the proposals. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - + -### Params -Params defines the set of params for the distribution module. +### QueryProposalsResponse +QueryProposalsResponse is the response type for the Query/Proposals RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `community_tax` | [string](#string) | | | -| `base_proposer_reward` | [string](#string) | | | -| `bonus_proposer_reward` | [string](#string) | | | -| `withdraw_addr_enabled` | [bool](#bool) | | | +| `proposals` | [Proposal](#cosmos.gov.v1beta1.Proposal) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - + -### ValidatorAccumulatedCommission -ValidatorAccumulatedCommission represents accumulated commission -for a validator kept as a running counter, can be withdrawn at any time. +### QueryTallyResultRequest +QueryTallyResultRequest is the request type for the Query/Tally RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `commission` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | - + -### ValidatorCurrentRewards -ValidatorCurrentRewards represents current rewards and current -period for a validator kept as a running counter and incremented -each block as long as the validator's tokens remain constant. +### QueryTallyResultResponse +QueryTallyResultResponse is the response type for the Query/Tally RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | -| `period` | [uint64](#uint64) | | | +| `tally` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | tally defines the requested tally. | - + -### ValidatorHistoricalRewards -ValidatorHistoricalRewards represents historical rewards for a validator. -Height is implicit within the store key. -Cumulative reward ratio is the sum from the zeroeth period -until this period of rewards / tokens, per the spec. -The reference count indicates the number of objects -which might need to reference this historical entry at any point. -ReferenceCount = - number of outstanding delegations which ended the associated period (and - might need to read that record) - + number of slashes which ended the associated period (and might need to - read that record) - + one per validator for the zeroeth period, set on initialization +### QueryVoteRequest +QueryVoteRequest is the request type for the Query/Vote RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `cumulative_reward_ratio` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | -| `reference_count` | [uint32](#uint32) | | | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `voter` | [string](#string) | | voter defines the oter address for the proposals. | - + -### ValidatorOutstandingRewards -ValidatorOutstandingRewards represents outstanding (un-withdrawn) rewards -for a validator inexpensive to track, allows simple sanity checks. +### QueryVoteResponse +QueryVoteResponse is the response type for the Query/Vote RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `vote` | [Vote](#cosmos.gov.v1beta1.Vote) | | vote defined the queried vote. | - + -### ValidatorSlashEvent -ValidatorSlashEvent represents a validator slash event. -Height is implicit within the store key. -This is needed to calculate appropriate amount of staking tokens -for delegations which are withdrawn after a slash has occurred. +### QueryVotesRequest +QueryVotesRequest is the request type for the Query/Votes RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_period` | [uint64](#uint64) | | | -| `fraction` | [string](#string) | | | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - + -### ValidatorSlashEvents -ValidatorSlashEvents is a collection of ValidatorSlashEvent messages. +### QueryVotesResponse +QueryVotesResponse is the response type for the Query/Votes RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_slash_events` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | repeated | | +| `votes` | [Vote](#cosmos.gov.v1beta1.Vote) | repeated | votes defined the queried votes. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | @@ -3267,155 +3390,195 @@ ValidatorSlashEvents is a collection of ValidatorSlashEvent messages. + + + +### Query +Query defines the gRPC querier service for gov module + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Proposal` | [QueryProposalRequest](#cosmos.gov.v1beta1.QueryProposalRequest) | [QueryProposalResponse](#cosmos.gov.v1beta1.QueryProposalResponse) | Proposal queries proposal details based on ProposalID. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}| +| `Proposals` | [QueryProposalsRequest](#cosmos.gov.v1beta1.QueryProposalsRequest) | [QueryProposalsResponse](#cosmos.gov.v1beta1.QueryProposalsResponse) | Proposals queries all proposals based on given status. | GET|/cosmos/gov/v1beta1/proposals| +| `Vote` | [QueryVoteRequest](#cosmos.gov.v1beta1.QueryVoteRequest) | [QueryVoteResponse](#cosmos.gov.v1beta1.QueryVoteResponse) | Vote queries voted information based on proposalID, voterAddr. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/votes/{voter}| +| `Votes` | [QueryVotesRequest](#cosmos.gov.v1beta1.QueryVotesRequest) | [QueryVotesResponse](#cosmos.gov.v1beta1.QueryVotesResponse) | Votes queries votes of a given proposal. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/votes| +| `Params` | [QueryParamsRequest](#cosmos.gov.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.gov.v1beta1.QueryParamsResponse) | Params queries all parameters of the gov module. | GET|/cosmos/gov/v1beta1/params/{params_type}| +| `Deposit` | [QueryDepositRequest](#cosmos.gov.v1beta1.QueryDepositRequest) | [QueryDepositResponse](#cosmos.gov.v1beta1.QueryDepositResponse) | Deposit queries single deposit information based proposalID, depositAddr. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits/{depositor}| +| `Deposits` | [QueryDepositsRequest](#cosmos.gov.v1beta1.QueryDepositsRequest) | [QueryDepositsResponse](#cosmos.gov.v1beta1.QueryDepositsResponse) | Deposits queries all deposits of a single proposal. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits| +| `TallyResult` | [QueryTallyResultRequest](#cosmos.gov.v1beta1.QueryTallyResultRequest) | [QueryTallyResultResponse](#cosmos.gov.v1beta1.QueryTallyResultResponse) | TallyResult queries the tally of a proposal vote. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/tally| + - +

      Top

      -## cosmos/distribution/v1beta1/genesis.proto +## cosmos/gov/v1beta1/tx.proto - + -### DelegatorStartingInfoRecord -DelegatorStartingInfoRecord used for import / export via genesis json. +### MsgDeposit +MsgDeposit defines a message to submit a deposit to an existing proposal. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | delegator_address is the address of the delegator. | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `starting_info` | [DelegatorStartingInfo](#cosmos.distribution.v1beta1.DelegatorStartingInfo) | | starting_info defines the starting info of a delegator. | +| `proposal_id` | [uint64](#uint64) | | | +| `depositor` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - + -### DelegatorWithdrawInfo -DelegatorWithdrawInfo is the address for where distributions rewards are -withdrawn to by default this struct is only used at genesis to feed in -default withdraw addresses. +### MsgDepositResponse +MsgDepositResponse defines the Msg/Deposit response type. + + + + + + + + +### MsgSubmitProposal +MsgSubmitProposal defines an sdk.Msg type that supports submitting arbitrary +proposal Content. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | delegator_address is the address of the delegator. | -| `withdraw_address` | [string](#string) | | withdraw_address is the address to withdraw the delegation rewards to. | +| `content` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `initial_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `proposer` | [string](#string) | | | - + -### GenesisState -GenesisState defines the distribution module's genesis state. +### MsgSubmitProposalResponse +MsgSubmitProposalResponse defines the Msg/SubmitProposal response type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.distribution.v1beta1.Params) | | params defines all the paramaters of the module. | -| `fee_pool` | [FeePool](#cosmos.distribution.v1beta1.FeePool) | | fee_pool defines the fee pool at genesis. | -| `delegator_withdraw_infos` | [DelegatorWithdrawInfo](#cosmos.distribution.v1beta1.DelegatorWithdrawInfo) | repeated | fee_pool defines the delegator withdraw infos at genesis. | -| `previous_proposer` | [string](#string) | | fee_pool defines the previous proposer at genesis. | -| `outstanding_rewards` | [ValidatorOutstandingRewardsRecord](#cosmos.distribution.v1beta1.ValidatorOutstandingRewardsRecord) | repeated | fee_pool defines the outstanding rewards of all validators at genesis. | -| `validator_accumulated_commissions` | [ValidatorAccumulatedCommissionRecord](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommissionRecord) | repeated | fee_pool defines the accumulated commisions of all validators at genesis. | -| `validator_historical_rewards` | [ValidatorHistoricalRewardsRecord](#cosmos.distribution.v1beta1.ValidatorHistoricalRewardsRecord) | repeated | fee_pool defines the historical rewards of all validators at genesis. | -| `validator_current_rewards` | [ValidatorCurrentRewardsRecord](#cosmos.distribution.v1beta1.ValidatorCurrentRewardsRecord) | repeated | fee_pool defines the current rewards of all validators at genesis. | -| `delegator_starting_infos` | [DelegatorStartingInfoRecord](#cosmos.distribution.v1beta1.DelegatorStartingInfoRecord) | repeated | fee_pool defines the delegator starting infos at genesis. | -| `validator_slash_events` | [ValidatorSlashEventRecord](#cosmos.distribution.v1beta1.ValidatorSlashEventRecord) | repeated | fee_pool defines the validator slash events at genesis. | +| `proposal_id` | [uint64](#uint64) | | | - + -### ValidatorAccumulatedCommissionRecord -ValidatorAccumulatedCommissionRecord is used for import / export via genesis -json. +### MsgVote +MsgVote defines a message to cast a vote. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `accumulated` | [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) | | accumulated is the accumulated commission of a validator. | +| `proposal_id` | [uint64](#uint64) | | | +| `voter` | [string](#string) | | | +| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | - + + +### MsgVoteResponse +MsgVoteResponse defines the Msg/Vote response type. -### ValidatorCurrentRewardsRecord -ValidatorCurrentRewardsRecord is used for import / export via genesis json. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `rewards` | [ValidatorCurrentRewards](#cosmos.distribution.v1beta1.ValidatorCurrentRewards) | | rewards defines the current rewards of a validator. | + + + - + -### ValidatorHistoricalRewardsRecord -ValidatorHistoricalRewardsRecord is used for import / export via genesis -json. +### Msg +Msg defines the bank Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `SubmitProposal` | [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) | [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) | SubmitProposal defines a method to create new proposal given a content. | | +| `Vote` | [MsgVote](#cosmos.gov.v1beta1.MsgVote) | [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) | Vote defines a method to add a vote on a specific proposal. | | +| `Deposit` | [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) | [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) | Deposit defines a method to add deposit on a specific proposal. | | + + + + + + +

      Top

      + +## cosmos/gov/v1beta1/genesis.proto + + + + + +### GenesisState +GenesisState defines the gov module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `period` | [uint64](#uint64) | | period defines the period the historical rewards apply to. | -| `rewards` | [ValidatorHistoricalRewards](#cosmos.distribution.v1beta1.ValidatorHistoricalRewards) | | rewards defines the historical rewards of a validator. | - +| `starting_proposal_id` | [uint64](#uint64) | | starting_proposal_id is the ID of the starting proposal. | +| `deposits` | [Deposit](#cosmos.gov.v1beta1.Deposit) | repeated | deposits defines all the deposits present at genesis. | +| `votes` | [Vote](#cosmos.gov.v1beta1.Vote) | repeated | votes defines all the votes present at genesis. | +| `proposals` | [Proposal](#cosmos.gov.v1beta1.Proposal) | repeated | proposals defines all the proposals present at genesis. | +| `deposit_params` | [DepositParams](#cosmos.gov.v1beta1.DepositParams) | | params defines all the paramaters of related to deposit. | +| `voting_params` | [VotingParams](#cosmos.gov.v1beta1.VotingParams) | | params defines all the paramaters of related to voting. | +| `tally_params` | [TallyParams](#cosmos.gov.v1beta1.TallyParams) | | params defines all the paramaters of related to tally. | - + -### ValidatorOutstandingRewardsRecord -ValidatorOutstandingRewardsRecord is used for import/export via genesis json. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `outstanding_rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | outstanding_rewards represents the oustanding rewards of a validator. | + + +

      Top

      + +## cosmos/genutil/v1beta1/genesis.proto - + -### ValidatorSlashEventRecord -ValidatorSlashEventRecord is used for import / export via genesis json. +### GenesisState +GenesisState defines the raw genesis transaction in JSON. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `height` | [uint64](#uint64) | | height defines the block height at which the slash event occured. | -| `period` | [uint64](#uint64) | | period is the period of the slash event. | -| `validator_slash_event` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | | validator_slash_event describes the slash event. | +| `gen_txs` | [bytes](#bytes) | repeated | gen_txs defines the genesis transactions. | @@ -3835,184 +3998,438 @@ MsgWithdrawDelegatorRewardResponse defines the Msg/WithdrawDelegatorReward respo - + + +### MsgWithdrawValidatorCommission +MsgWithdrawValidatorCommission withdraws the full commission to the validator +address. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | | + + + + + + + + +### MsgWithdrawValidatorCommissionResponse +MsgWithdrawValidatorCommissionResponse defines the Msg/WithdrawValidatorCommission response type. + + + + + + + + + + + + + + +### Msg +Msg defines the distribution Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `SetWithdrawAddress` | [MsgSetWithdrawAddress](#cosmos.distribution.v1beta1.MsgSetWithdrawAddress) | [MsgSetWithdrawAddressResponse](#cosmos.distribution.v1beta1.MsgSetWithdrawAddressResponse) | SetWithdrawAddress defines a method to change the withdraw address for a delegator (or validator self-delegation). | | +| `WithdrawDelegatorReward` | [MsgWithdrawDelegatorReward](#cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward) | [MsgWithdrawDelegatorRewardResponse](#cosmos.distribution.v1beta1.MsgWithdrawDelegatorRewardResponse) | WithdrawDelegatorReward defines a method to withdraw rewards of delegator from a single validator. | | +| `WithdrawValidatorCommission` | [MsgWithdrawValidatorCommission](#cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission) | [MsgWithdrawValidatorCommissionResponse](#cosmos.distribution.v1beta1.MsgWithdrawValidatorCommissionResponse) | WithdrawValidatorCommission defines a method to withdraw the full commission to the validator address. | | +| `FundCommunityPool` | [MsgFundCommunityPool](#cosmos.distribution.v1beta1.MsgFundCommunityPool) | [MsgFundCommunityPoolResponse](#cosmos.distribution.v1beta1.MsgFundCommunityPoolResponse) | FundCommunityPool defines a method to allow an account to directly fund the community pool. | | + + + + + + +

      Top

      + +## cosmos/distribution/v1beta1/genesis.proto + + + + + +### DelegatorStartingInfoRecord +DelegatorStartingInfoRecord used for import / export via genesis json. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | delegator_address is the address of the delegator. | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `starting_info` | [DelegatorStartingInfo](#cosmos.distribution.v1beta1.DelegatorStartingInfo) | | starting_info defines the starting info of a delegator. | + + + + + + + + +### DelegatorWithdrawInfo +DelegatorWithdrawInfo is the address for where distributions rewards are +withdrawn to by default this struct is only used at genesis to feed in +default withdraw addresses. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | delegator_address is the address of the delegator. | +| `withdraw_address` | [string](#string) | | withdraw_address is the address to withdraw the delegation rewards to. | + + + + + + + + +### GenesisState +GenesisState defines the distribution module's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params` | [Params](#cosmos.distribution.v1beta1.Params) | | params defines all the paramaters of the module. | +| `fee_pool` | [FeePool](#cosmos.distribution.v1beta1.FeePool) | | fee_pool defines the fee pool at genesis. | +| `delegator_withdraw_infos` | [DelegatorWithdrawInfo](#cosmos.distribution.v1beta1.DelegatorWithdrawInfo) | repeated | fee_pool defines the delegator withdraw infos at genesis. | +| `previous_proposer` | [string](#string) | | fee_pool defines the previous proposer at genesis. | +| `outstanding_rewards` | [ValidatorOutstandingRewardsRecord](#cosmos.distribution.v1beta1.ValidatorOutstandingRewardsRecord) | repeated | fee_pool defines the outstanding rewards of all validators at genesis. | +| `validator_accumulated_commissions` | [ValidatorAccumulatedCommissionRecord](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommissionRecord) | repeated | fee_pool defines the accumulated commisions of all validators at genesis. | +| `validator_historical_rewards` | [ValidatorHistoricalRewardsRecord](#cosmos.distribution.v1beta1.ValidatorHistoricalRewardsRecord) | repeated | fee_pool defines the historical rewards of all validators at genesis. | +| `validator_current_rewards` | [ValidatorCurrentRewardsRecord](#cosmos.distribution.v1beta1.ValidatorCurrentRewardsRecord) | repeated | fee_pool defines the current rewards of all validators at genesis. | +| `delegator_starting_infos` | [DelegatorStartingInfoRecord](#cosmos.distribution.v1beta1.DelegatorStartingInfoRecord) | repeated | fee_pool defines the delegator starting infos at genesis. | +| `validator_slash_events` | [ValidatorSlashEventRecord](#cosmos.distribution.v1beta1.ValidatorSlashEventRecord) | repeated | fee_pool defines the validator slash events at genesis. | + + + + + + + + +### ValidatorAccumulatedCommissionRecord +ValidatorAccumulatedCommissionRecord is used for import / export via genesis +json. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `accumulated` | [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) | | accumulated is the accumulated commission of a validator. | + + + + + + + + +### ValidatorCurrentRewardsRecord +ValidatorCurrentRewardsRecord is used for import / export via genesis json. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `rewards` | [ValidatorCurrentRewards](#cosmos.distribution.v1beta1.ValidatorCurrentRewards) | | rewards defines the current rewards of a validator. | + + + + + + + + +### ValidatorHistoricalRewardsRecord +ValidatorHistoricalRewardsRecord is used for import / export via genesis +json. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `period` | [uint64](#uint64) | | period defines the period the historical rewards apply to. | +| `rewards` | [ValidatorHistoricalRewards](#cosmos.distribution.v1beta1.ValidatorHistoricalRewards) | | rewards defines the historical rewards of a validator. | + + + + + + + + +### ValidatorOutstandingRewardsRecord +ValidatorOutstandingRewardsRecord is used for import/export via genesis json. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `outstanding_rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | outstanding_rewards represents the oustanding rewards of a validator. | + + + + + + + + +### ValidatorSlashEventRecord +ValidatorSlashEventRecord is used for import / export via genesis json. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `height` | [uint64](#uint64) | | height defines the block height at which the slash event occured. | +| `period` | [uint64](#uint64) | | period is the period of the slash event. | +| `validator_slash_event` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | | validator_slash_event describes the slash event. | + + + + + + + + + + + + + + + + +

      Top

      + +## cosmos/distribution/v1beta1/distribution.proto + + + + + +### CommunityPoolSpendProposal +CommunityPoolSpendProposal details a proposal for use of community funds, +together with how many coins are proposed to be spent, and to which +recipient account. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `recipient` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | + + + + + + + -### MsgWithdrawValidatorCommission -MsgWithdrawValidatorCommission withdraws the full commission to the validator -address. +### CommunityPoolSpendProposalWithDeposit +CommunityPoolSpendProposalWithDeposit defines a CommunityPoolSpendProposal +with a deposit | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | | - - +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `recipient` | [string](#string) | | | +| `amount` | [string](#string) | | | +| `deposit` | [string](#string) | | | - -### MsgWithdrawValidatorCommissionResponse -MsgWithdrawValidatorCommissionResponse defines the Msg/WithdrawValidatorCommission response type. + +### DelegationDelegatorReward +DelegationDelegatorReward represents the properties +of a delegator's delegation reward. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | | +| `reward` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - - - - -### Msg -Msg defines the distribution Msg service. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `SetWithdrawAddress` | [MsgSetWithdrawAddress](#cosmos.distribution.v1beta1.MsgSetWithdrawAddress) | [MsgSetWithdrawAddressResponse](#cosmos.distribution.v1beta1.MsgSetWithdrawAddressResponse) | SetWithdrawAddress defines a method to change the withdraw address for a delegator (or validator self-delegation). | | -| `WithdrawDelegatorReward` | [MsgWithdrawDelegatorReward](#cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward) | [MsgWithdrawDelegatorRewardResponse](#cosmos.distribution.v1beta1.MsgWithdrawDelegatorRewardResponse) | WithdrawDelegatorReward defines a method to withdraw rewards of delegator from a single validator. | | -| `WithdrawValidatorCommission` | [MsgWithdrawValidatorCommission](#cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission) | [MsgWithdrawValidatorCommissionResponse](#cosmos.distribution.v1beta1.MsgWithdrawValidatorCommissionResponse) | WithdrawValidatorCommission defines a method to withdraw the full commission to the validator address. | | -| `FundCommunityPool` | [MsgFundCommunityPool](#cosmos.distribution.v1beta1.MsgFundCommunityPool) | [MsgFundCommunityPoolResponse](#cosmos.distribution.v1beta1.MsgFundCommunityPoolResponse) | FundCommunityPool defines a method to allow an account to directly fund the community pool. | | +### DelegatorStartingInfo +DelegatorStartingInfo represents the starting info for a delegator reward +period. It tracks the previous validator period, the delegation's amount of +staking token, and the creation height (to check later on if any slashes have +occurred). NOTE: Even though validators are slashed to whole staking tokens, +the delegators within the validator may be left with less than a full token, +thus sdk.Dec is used. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `previous_period` | [uint64](#uint64) | | | +| `stake` | [string](#string) | | | +| `height` | [uint64](#uint64) | | | - -

      Top

      -## cosmos/evidence/v1beta1/evidence.proto - + -### Equivocation -Equivocation implements the Evidence interface and defines evidence of double -signing misbehavior. +### FeePool +FeePool is the global fee pool for distribution. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | | -| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `power` | [int64](#int64) | | | -| `consensus_address` | [string](#string) | | | +| `community_pool` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - - + - +### Params +Params defines the set of params for the distribution module. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `community_tax` | [string](#string) | | | +| `base_proposer_reward` | [string](#string) | | | +| `bonus_proposer_reward` | [string](#string) | | | +| `withdraw_addr_enabled` | [bool](#bool) | | | - -

      Top

      -## cosmos/evidence/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the evidence module's genesis state. +### ValidatorAccumulatedCommission +ValidatorAccumulatedCommission represents accumulated commission +for a validator kept as a running counter, can be withdrawn at any time. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence defines all the evidence at genesis. | +| `commission` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - - + - +### ValidatorCurrentRewards +ValidatorCurrentRewards represents current rewards and current +period for a validator kept as a running counter and incremented +each block as long as the validator's tokens remain constant. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `period` | [uint64](#uint64) | | | - -

      Top

      -## cosmos/evidence/v1beta1/query.proto - + -### QueryAllEvidenceRequest -QueryEvidenceRequest is the request type for the Query/AllEvidence RPC -method. +### ValidatorHistoricalRewards +ValidatorHistoricalRewards represents historical rewards for a validator. +Height is implicit within the store key. +Cumulative reward ratio is the sum from the zeroeth period +until this period of rewards / tokens, per the spec. +The reference count indicates the number of objects +which might need to reference this historical entry at any point. +ReferenceCount = + number of outstanding delegations which ended the associated period (and + might need to read that record) + + number of slashes which ended the associated period (and might need to + read that record) + + one per validator for the zeroeth period, set on initialization | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +| `cumulative_reward_ratio` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `reference_count` | [uint32](#uint32) | | | - + -### QueryAllEvidenceResponse -QueryAllEvidenceResponse is the response type for the Query/AllEvidence RPC -method. +### ValidatorOutstandingRewards +ValidatorOutstandingRewards represents outstanding (un-withdrawn) rewards +for a validator inexpensive to track, allows simple sanity checks. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence returns all evidences. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - + -### QueryEvidenceRequest -QueryEvidenceRequest is the request type for the Query/Evidence RPC method. +### ValidatorSlashEvent +ValidatorSlashEvent represents a validator slash event. +Height is implicit within the store key. +This is needed to calculate appropriate amount of staking tokens +for delegations which are withdrawn after a slash has occurred. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `evidence_hash` | [bytes](#bytes) | | evidence_hash defines the hash of the requested evidence. | +| `validator_period` | [uint64](#uint64) | | | +| `fraction` | [string](#string) | | | - + -### QueryEvidenceResponse -QueryEvidenceResponse is the response type for the Query/Evidence RPC method. +### ValidatorSlashEvents +ValidatorSlashEvents is a collection of ValidatorSlashEvent messages. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | evidence returns the requested evidence. | +| `validator_slash_events` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | repeated | | @@ -4024,95 +4441,102 @@ QueryEvidenceResponse is the response type for the Query/Evidence RPC method. - - - -### Query -Query defines the gRPC querier service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Evidence` | [QueryEvidenceRequest](#cosmos.evidence.v1beta1.QueryEvidenceRequest) | [QueryEvidenceResponse](#cosmos.evidence.v1beta1.QueryEvidenceResponse) | Evidence queries evidence based on evidence hash. | GET|/cosmos/evidence/v1beta1/evidence/{evidence_hash}| -| `AllEvidence` | [QueryAllEvidenceRequest](#cosmos.evidence.v1beta1.QueryAllEvidenceRequest) | [QueryAllEvidenceResponse](#cosmos.evidence.v1beta1.QueryAllEvidenceResponse) | AllEvidence queries all evidence. | GET|/cosmos/evidence/v1beta1/evidence| - - +

      Top

      -## cosmos/evidence/v1beta1/tx.proto +## cosmos/upgrade/v1beta1/query.proto - + -### MsgSubmitEvidence -MsgSubmitEvidence represents a message that supports submitting arbitrary -Evidence of misbehavior such as equivocation or counterfactual signing. +### QueryAppliedPlanRequest +QueryCurrentPlanRequest is the request type for the Query/AppliedPlan RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `submitter` | [string](#string) | | | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `name` | [string](#string) | | name is the name of the applied plan to query for. | - + -### MsgSubmitEvidenceResponse -MsgSubmitEvidenceResponse defines the Msg/SubmitEvidence response type. +### QueryAppliedPlanResponse +QueryAppliedPlanResponse is the response type for the Query/AppliedPlan RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `hash` | [bytes](#bytes) | | hash defines the hash of the evidence. | +| `height` | [int64](#int64) | | height is the block height at which the plan was applied. | - - + - +### QueryCurrentPlanRequest +QueryCurrentPlanRequest is the request type for the Query/CurrentPlan RPC +method. - -### Msg -Msg defines the evidence Msg service. -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `SubmitEvidence` | [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) | [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) | SubmitEvidence submits an arbitrary Evidence of misbehavior such as equivocation or counterfactual signing. | | - + +### QueryCurrentPlanResponse +QueryCurrentPlanResponse is the response type for the Query/CurrentPlan RPC +method. - -

      Top

      -## cosmos/genutil/v1beta1/genesis.proto +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | plan is the current upgrade plan. | + - -### GenesisState -GenesisState defines the raw genesis transaction in JSON. + + + +### QueryUpgradedConsensusStateRequest +QueryUpgradedConsensusStateRequest is the request type for the Query/UpgradedConsensusState +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `gen_txs` | [bytes](#bytes) | repeated | gen_txs defines the genesis transactions. | +| `last_height` | [int64](#int64) | | last height of the current chain must be sent in request as this is the height under which next consensus state is stored | + + + + + + + + +### QueryUpgradedConsensusStateResponse +QueryUpgradedConsensusStateResponse is the response type for the Query/UpgradedConsensusState +RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `upgraded_consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | @@ -4124,490 +4548,515 @@ GenesisState defines the raw genesis transaction in JSON. + + + +### Query +Query defines the gRPC upgrade querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `CurrentPlan` | [QueryCurrentPlanRequest](#cosmos.upgrade.v1beta1.QueryCurrentPlanRequest) | [QueryCurrentPlanResponse](#cosmos.upgrade.v1beta1.QueryCurrentPlanResponse) | CurrentPlan queries the current upgrade plan. | GET|/cosmos/upgrade/v1beta1/current_plan| +| `AppliedPlan` | [QueryAppliedPlanRequest](#cosmos.upgrade.v1beta1.QueryAppliedPlanRequest) | [QueryAppliedPlanResponse](#cosmos.upgrade.v1beta1.QueryAppliedPlanResponse) | AppliedPlan queries a previously applied upgrade plan by its name. | GET|/cosmos/upgrade/v1beta1/applied_plan/{name}| +| `UpgradedConsensusState` | [QueryUpgradedConsensusStateRequest](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateRequest) | [QueryUpgradedConsensusStateResponse](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse) | UpgradedConsensusState queries the consensus state that will serve as a trusted kernel for the next version of this chain. It will only be stored at the last height of this chain. UpgradedConsensusState RPC not supported with legacy querier | GET|/cosmos/upgrade/v1beta1/upgraded_consensus_state/{last_height}| + - +

      Top

      -## cosmos/gov/v1beta1/gov.proto +## cosmos/upgrade/v1beta1/upgrade.proto - + -### Deposit -Deposit defines an amount deposited by an account address to an active -proposal. +### CancelSoftwareUpgradeProposal +CancelSoftwareUpgradeProposal is a gov Content type for cancelling a software +upgrade. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `depositor` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | - + -### DepositParams -DepositParams defines the params for deposits on governance proposals. +### Plan +Plan specifies information about a planned upgrade and when it should occur. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `min_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | Minimum deposit for a proposal to enter voting period. | -| `max_deposit_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months. | +| `name` | [string](#string) | | Sets the name for the upgrade. This name will be used by the upgraded version of the software to apply any special "on-upgrade" commands during the first BeginBlock method after the upgrade is applied. It is also used to detect whether a software version can handle a given upgrade. If no upgrade handler with this name has been set in the software, it will be assumed that the software is out-of-date when the upgrade Time or Height is reached and the software will exit. | +| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | The time after which the upgrade must be performed. Leave set to its zero value to use a pre-defined Height instead. | +| `height` | [int64](#int64) | | The height at which the upgrade must be performed. Only used if Time is not set. | +| `info` | [string](#string) | | Any application specific upgrade info to be included on-chain such as a git commit that validators could automatically upgrade to | +| `upgraded_client_state` | [google.protobuf.Any](#google.protobuf.Any) | | IBC-enabled chains can opt-in to including the upgraded client state in its upgrade plan This will make the chain commit to the correct upgraded (self) client state before the upgrade occurs, so that connecting chains can verify that the new upgraded client is valid by verifying a proof on the previous version of the chain. This will allow IBC connections to persist smoothly across planned chain upgrades | - + -### Proposal -Proposal defines the core field members of a governance proposal. +### SoftwareUpgradeProposal +SoftwareUpgradeProposal is a gov Content type for initiating a software +upgrade. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `content` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `status` | [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) | | | -| `final_tally_result` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | | -| `submit_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `deposit_end_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `total_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `voting_start_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `voting_end_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | | + - + -### TallyParams -TallyParams defines the params for tallying votes on governance proposals. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `quorum` | [bytes](#bytes) | | Minimum percentage of total stake needed to vote for a result to be considered valid. | -| `threshold` | [bytes](#bytes) | | Minimum proportion of Yes votes for proposal to pass. Default value: 0.5. | -| `veto_threshold` | [bytes](#bytes) | | Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Default value: 1/3. | + +

      Top

      +## cosmos/base/kv/v1beta1/kv.proto - + -### TallyResult -TallyResult defines a standard tally for a governance proposal. +### Pair +Pair defines a key/value bytes tuple. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `yes` | [string](#string) | | | -| `abstain` | [string](#string) | | | -| `no` | [string](#string) | | | -| `no_with_veto` | [string](#string) | | | +| `key` | [bytes](#bytes) | | | +| `value` | [bytes](#bytes) | | | - + -### TextProposal -TextProposal defines a standard text proposal whose changes need to be -manually updated in case of approval. +### Pairs +Pairs defines a repeated slice of Pair objects. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | +| `pairs` | [Pair](#cosmos.base.kv.v1beta1.Pair) | repeated | | + - + -### Vote -Vote defines a vote on a governance proposal. -A Vote consists of a proposal ID, the voter, and the vote option. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `voter` | [string](#string) | | | -| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | + +

      Top

      +## cosmos/base/abci/v1beta1/abci.proto - + -### VotingParams -VotingParams defines the params for voting on governance proposals. +### ABCIMessageLog +ABCIMessageLog defines a structure containing an indexed tx ABCI message log. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `voting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Length of the voting period. | - +| `msg_index` | [uint32](#uint32) | | | +| `log` | [string](#string) | | | +| `events` | [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) | repeated | Events contains a slice of Event objects that were emitted during some execution. | - - + -### ProposalStatus -ProposalStatus enumerates the valid statuses of a proposal. +### Attribute +Attribute defines an attribute wrapper where the key and value are +strings instead of raw bytes. -| Name | Number | Description | -| ---- | ------ | ----------- | -| PROPOSAL_STATUS_UNSPECIFIED | 0 | PROPOSAL_STATUS_UNSPECIFIED defines the default propopsal status. | -| PROPOSAL_STATUS_DEPOSIT_PERIOD | 1 | PROPOSAL_STATUS_DEPOSIT_PERIOD defines a proposal status during the deposit period. | -| PROPOSAL_STATUS_VOTING_PERIOD | 2 | PROPOSAL_STATUS_VOTING_PERIOD defines a proposal status during the voting period. | -| PROPOSAL_STATUS_PASSED | 3 | PROPOSAL_STATUS_PASSED defines a proposal status of a proposal that has passed. | -| PROPOSAL_STATUS_REJECTED | 4 | PROPOSAL_STATUS_REJECTED defines a proposal status of a proposal that has been rejected. | -| PROPOSAL_STATUS_FAILED | 5 | PROPOSAL_STATUS_FAILED defines a proposal status of a proposal that has failed. | +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [string](#string) | | | +| `value` | [string](#string) | | | - -### VoteOption -VoteOption enumerates the valid vote options for a given governance proposal. -| Name | Number | Description | -| ---- | ------ | ----------- | -| VOTE_OPTION_UNSPECIFIED | 0 | VOTE_OPTION_UNSPECIFIED defines a no-op vote option. | -| VOTE_OPTION_YES | 1 | VOTE_OPTION_YES defines a yes vote option. | -| VOTE_OPTION_ABSTAIN | 2 | VOTE_OPTION_ABSTAIN defines an abstain vote option. | -| VOTE_OPTION_NO | 3 | VOTE_OPTION_NO defines a no vote option. | -| VOTE_OPTION_NO_WITH_VETO | 4 | VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. | - + - +### GasInfo +GasInfo defines tx execution gas context. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `gas_wanted` | [uint64](#uint64) | | GasWanted is the maximum units of work we allow this tx to perform. | +| `gas_used` | [uint64](#uint64) | | GasUsed is the amount of gas actually consumed. | - -

      Top

      -## cosmos/gov/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the gov module's genesis state. +### MsgData +MsgData defines the data returned in a Result object during message +execution. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `starting_proposal_id` | [uint64](#uint64) | | starting_proposal_id is the ID of the starting proposal. | -| `deposits` | [Deposit](#cosmos.gov.v1beta1.Deposit) | repeated | deposits defines all the deposits present at genesis. | -| `votes` | [Vote](#cosmos.gov.v1beta1.Vote) | repeated | votes defines all the votes present at genesis. | -| `proposals` | [Proposal](#cosmos.gov.v1beta1.Proposal) | repeated | proposals defines all the proposals present at genesis. | -| `deposit_params` | [DepositParams](#cosmos.gov.v1beta1.DepositParams) | | params defines all the paramaters of related to deposit. | -| `voting_params` | [VotingParams](#cosmos.gov.v1beta1.VotingParams) | | params defines all the paramaters of related to voting. | -| `tally_params` | [TallyParams](#cosmos.gov.v1beta1.TallyParams) | | params defines all the paramaters of related to tally. | +| `msg_type` | [string](#string) | | | +| `data` | [bytes](#bytes) | | | - - + - +### Result +Result is the union of ResponseFormat and ResponseCheckTx. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `data` | [bytes](#bytes) | | Data is any data returned from message or handler execution. It MUST be length prefixed in order to separate data from multiple message executions. | +| `log` | [string](#string) | | Log contains the log information from message or handler execution. | +| `events` | [tendermint.abci.Event](#tendermint.abci.Event) | repeated | Events contains a slice of Event objects that were emitted during message or handler execution. | - -

      Top

      -## cosmos/gov/v1beta1/query.proto - + -### QueryDepositRequest -QueryDepositRequest is the request type for the Query/Deposit RPC method. +### SearchTxsResult +SearchTxsResult defines a structure for querying txs pageable | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `depositor` | [string](#string) | | depositor defines the deposit addresses from the proposals. | +| `total_count` | [uint64](#uint64) | | Count of all txs | +| `count` | [uint64](#uint64) | | Count of txs in current page | +| `page_number` | [uint64](#uint64) | | Index of current page, start from 1 | +| `page_total` | [uint64](#uint64) | | Count of total pages | +| `limit` | [uint64](#uint64) | | Max count txs per page | +| `txs` | [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | List of txs in current page | - + -### QueryDepositResponse -QueryDepositResponse is the response type for the Query/Deposit RPC method. +### SimulationResponse +SimulationResponse defines the response generated when a transaction is +successfully simulated. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `deposit` | [Deposit](#cosmos.gov.v1beta1.Deposit) | | deposit defines the requested deposit. | +| `gas_info` | [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | | +| `result` | [Result](#cosmos.base.abci.v1beta1.Result) | | | - + -### QueryDepositsRequest -QueryDepositsRequest is the request type for the Query/Deposits RPC method. +### StringEvent +StringEvent defines en Event object wrapper where all the attributes +contain key/value pairs that are strings instead of raw bytes. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +| `type` | [string](#string) | | | +| `attributes` | [Attribute](#cosmos.base.abci.v1beta1.Attribute) | repeated | | - + -### QueryDepositsResponse -QueryDepositsResponse is the response type for the Query/Deposits RPC method. +### TxMsgData +TxMsgData defines a list of MsgData. A transaction will have a MsgData object +for each message. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `deposits` | [Deposit](#cosmos.gov.v1beta1.Deposit) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | | - + + +### TxResponse +TxResponse defines a structure containing relevant tx data and metadata. The +tags are stringified and the log is JSON decoded. -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [int64](#int64) | | The block height | +| `txhash` | [string](#string) | | The transaction hash. | +| `codespace` | [string](#string) | | Namespace for the Code | +| `code` | [uint32](#uint32) | | Response code. | +| `data` | [string](#string) | | Result bytes, if any. | +| `raw_log` | [string](#string) | | The output of the application's logger (raw string). May be non-deterministic. | +| `logs` | [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) | repeated | The output of the application's logger (typed). May be non-deterministic. | +| `info` | [string](#string) | | Additional information. May be non-deterministic. | +| `gas_wanted` | [int64](#int64) | | Amount of gas requested for transaction. | +| `gas_used` | [int64](#int64) | | Amount of gas consumed by transaction. | +| `tx` | [google.protobuf.Any](#google.protobuf.Any) | | The request transaction bytes. | +| `timestamp` | [string](#string) | | Time of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time. | -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params_type` | [string](#string) | | params_type defines which parameters to query for, can be one of "voting", "tallying" or "deposit". | + + - + -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `voting_params` | [VotingParams](#cosmos.gov.v1beta1.VotingParams) | | voting_params defines the parameters related to voting. | -| `deposit_params` | [DepositParams](#cosmos.gov.v1beta1.DepositParams) | | deposit_params defines the parameters related to deposit. | -| `tally_params` | [TallyParams](#cosmos.gov.v1beta1.TallyParams) | | tally_params defines the parameters related to tally. | + +

      Top

      +## cosmos/base/query/v1beta1/pagination.proto + - +### PageRequest +PageRequest is to be embedded in gRPC request messages for efficient +pagination. Ex: -### QueryProposalRequest -QueryProposalRequest is the request type for the Query/Proposal RPC method. + message SomeRequest { + Foo some_parameter = 1; + PageRequest pagination = 2; + } | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `key` | [bytes](#bytes) | | key is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be set. | +| `offset` | [uint64](#uint64) | | offset is a numeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be set. | +| `limit` | [uint64](#uint64) | | limit is the total number of results to be returned in the result page. If left empty it will default to a value to be set by each app. | +| `count_total` | [bool](#bool) | | count_total is set to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. count_total is only respected when offset is used. It is ignored when key is set. | - + -### QueryProposalResponse -QueryProposalResponse is the response type for the Query/Proposal RPC method. +### PageResponse +PageResponse is to be embedded in gRPC response messages where the +corresponding request message has used PageRequest. + + message SomeResponse { + repeated Bar results = 1; + PageResponse page = 2; + } | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal` | [Proposal](#cosmos.gov.v1beta1.Proposal) | | | +| `next_key` | [bytes](#bytes) | | next_key is the key to be passed to PageRequest.key to query the next page most efficiently | +| `total` | [uint64](#uint64) | | total is total number of results available if PageRequest.count_total was set, its value is undefined otherwise | + - + -### QueryProposalsRequest -QueryProposalsRequest is the request type for the Query/Proposals RPC method. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_status` | [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) | | proposal_status defines the status of the proposals. | -| `voter` | [string](#string) | | voter defines the voter address for the proposals. | -| `depositor` | [string](#string) | | depositor defines the deposit addresses from the proposals. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + +

      Top

      +## cosmos/base/store/v1beta1/snapshot.proto - + -### QueryProposalsResponse -QueryProposalsResponse is the response type for the Query/Proposals RPC -method. +### SnapshotIAVLItem +SnapshotIAVLItem is an exported IAVL node. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposals` | [Proposal](#cosmos.gov.v1beta1.Proposal) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| `key` | [bytes](#bytes) | | | +| `value` | [bytes](#bytes) | | | +| `version` | [int64](#int64) | | | +| `height` | [int32](#int32) | | | - + -### QueryTallyResultRequest -QueryTallyResultRequest is the request type for the Query/Tally RPC method. +### SnapshotItem +SnapshotItem is an item contained in a rootmulti.Store snapshot. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `store` | [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) | | | +| `iavl` | [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) | | | - + -### QueryTallyResultResponse -QueryTallyResultResponse is the response type for the Query/Tally RPC method. +### SnapshotStoreItem +SnapshotStoreItem contains metadata about a snapshotted store. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `tally` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | tally defines the requested tally. | +| `name` | [string](#string) | | | + - + -### QueryVoteRequest -QueryVoteRequest is the request type for the Query/Vote RPC method. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `voter` | [string](#string) | | voter defines the oter address for the proposals. | + +

      Top

      +## cosmos/base/store/v1beta1/commit_info.proto - + -### QueryVoteResponse -QueryVoteResponse is the response type for the Query/Vote RPC method. +### CommitID +CommitID defines the committment information when a specific store is +committed. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `vote` | [Vote](#cosmos.gov.v1beta1.Vote) | | vote defined the queried vote. | +| `version` | [int64](#int64) | | | +| `hash` | [bytes](#bytes) | | | - + -### QueryVotesRequest -QueryVotesRequest is the request type for the Query/Votes RPC method. +### CommitInfo +CommitInfo defines commit information used by the multi-store when committing +a version/height. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +| `version` | [int64](#int64) | | | +| `store_infos` | [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) | repeated | | - + -### QueryVotesResponse -QueryVotesResponse is the response type for the Query/Votes RPC method. +### StoreInfo +StoreInfo defines store-specific commit information. It contains a reference +between a store name and the commit ID. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `votes` | [Vote](#cosmos.gov.v1beta1.Vote) | repeated | votes defined the queried votes. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| `name` | [string](#string) | | | +| `commit_id` | [CommitID](#cosmos.base.store.v1beta1.CommitID) | | | @@ -4619,368 +5068,324 @@ QueryVotesResponse is the response type for the Query/Votes RPC method. - - - -### Query -Query defines the gRPC querier service for gov module - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Proposal` | [QueryProposalRequest](#cosmos.gov.v1beta1.QueryProposalRequest) | [QueryProposalResponse](#cosmos.gov.v1beta1.QueryProposalResponse) | Proposal queries proposal details based on ProposalID. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}| -| `Proposals` | [QueryProposalsRequest](#cosmos.gov.v1beta1.QueryProposalsRequest) | [QueryProposalsResponse](#cosmos.gov.v1beta1.QueryProposalsResponse) | Proposals queries all proposals based on given status. | GET|/cosmos/gov/v1beta1/proposals| -| `Vote` | [QueryVoteRequest](#cosmos.gov.v1beta1.QueryVoteRequest) | [QueryVoteResponse](#cosmos.gov.v1beta1.QueryVoteResponse) | Vote queries voted information based on proposalID, voterAddr. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/votes/{voter}| -| `Votes` | [QueryVotesRequest](#cosmos.gov.v1beta1.QueryVotesRequest) | [QueryVotesResponse](#cosmos.gov.v1beta1.QueryVotesResponse) | Votes queries votes of a given proposal. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/votes| -| `Params` | [QueryParamsRequest](#cosmos.gov.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.gov.v1beta1.QueryParamsResponse) | Params queries all parameters of the gov module. | GET|/cosmos/gov/v1beta1/params/{params_type}| -| `Deposit` | [QueryDepositRequest](#cosmos.gov.v1beta1.QueryDepositRequest) | [QueryDepositResponse](#cosmos.gov.v1beta1.QueryDepositResponse) | Deposit queries single deposit information based proposalID, depositAddr. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits/{depositor}| -| `Deposits` | [QueryDepositsRequest](#cosmos.gov.v1beta1.QueryDepositsRequest) | [QueryDepositsResponse](#cosmos.gov.v1beta1.QueryDepositsResponse) | Deposits queries all deposits of a single proposal. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits| -| `TallyResult` | [QueryTallyResultRequest](#cosmos.gov.v1beta1.QueryTallyResultRequest) | [QueryTallyResultResponse](#cosmos.gov.v1beta1.QueryTallyResultResponse) | TallyResult queries the tally of a proposal vote. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/tally| - - +

      Top

      -## cosmos/gov/v1beta1/tx.proto +## cosmos/base/v1beta1/coin.proto - + -### MsgDeposit -MsgDeposit defines a message to submit a deposit to an existing proposal. +### Coin +Coin defines a token with a denomination and an amount. + +NOTE: The amount field is an Int which implements the custom method +signatures required by gogoproto. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `depositor` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - - - - - - - +| `denom` | [string](#string) | | | +| `amount` | [string](#string) | | | -### MsgDepositResponse -MsgDepositResponse defines the Msg/Deposit response type. + - +### DecCoin +DecCoin defines a token with a denomination and a decimal amount. -### MsgSubmitProposal -MsgSubmitProposal defines an sdk.Msg type that supports submitting arbitrary -proposal Content. +NOTE: The amount field is an Dec which implements the custom method +signatures required by gogoproto. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `content` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `initial_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `proposer` | [string](#string) | | | +| `denom` | [string](#string) | | | +| `amount` | [string](#string) | | | - + -### MsgSubmitProposalResponse -MsgSubmitProposalResponse defines the Msg/SubmitProposal response type. +### DecProto +DecProto defines a Protobuf wrapper around a Dec object. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | +| `dec` | [string](#string) | | | - + -### MsgVote -MsgVote defines a message to cast a vote. +### IntProto +IntProto defines a Protobuf wrapper around an Int object. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `voter` | [string](#string) | | | -| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | - - +| `int` | [string](#string) | | | - -### MsgVoteResponse -MsgVoteResponse defines the Msg/Vote response type. + + + + - - + +

      Top

      - +## cosmos/base/tendermint/v1beta1/query.proto - -### Msg -Msg defines the bank Msg service. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `SubmitProposal` | [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) | [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) | SubmitProposal defines a method to create new proposal given a content. | | -| `Vote` | [MsgVote](#cosmos.gov.v1beta1.MsgVote) | [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) | Vote defines a method to add a vote on a specific proposal. | | -| `Deposit` | [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) | [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) | Deposit defines a method to add deposit on a specific proposal. | | +### GetBlockByHeightRequest +GetBlockByHeightRequest is the request type for the Query/GetBlockByHeight RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [int64](#int64) | | | - -

      Top

      -## cosmos/mint/v1beta1/mint.proto - + -### Minter -Minter represents the minting state. +### GetBlockByHeightResponse +GetBlockByHeightResponse is the response type for the Query/GetBlockByHeight RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `inflation` | [string](#string) | | current annual inflation rate | -| `annual_provisions` | [string](#string) | | current annual expected provisions | - - +| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | +| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | - -### Params -Params holds parameters for the mint module. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `mint_denom` | [string](#string) | | type of coin to mint | -| `inflation_rate_change` | [string](#string) | | maximum annual change in inflation rate | -| `inflation_max` | [string](#string) | | maximum inflation rate | -| `inflation_min` | [string](#string) | | minimum inflation rate | -| `goal_bonded` | [string](#string) | | goal of percent bonded atoms | -| `blocks_per_year` | [uint64](#uint64) | | expected blocks per year | +### GetLatestBlockRequest +GetLatestBlockRequest is the request type for the Query/GetLatestBlock RPC method. - - + - +### GetLatestBlockResponse +GetLatestBlockResponse is the response type for the Query/GetLatestBlock RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | +| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | - -

      Top

      -## cosmos/mint/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the mint module's genesis state. +### GetLatestValidatorSetRequest +GetLatestValidatorSetRequest is the request type for the Query/GetValidatorSetByHeight RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `minter` | [Minter](#cosmos.mint.v1beta1.Minter) | | minter is a space for holding current inflation information. | -| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines all the paramaters of the module. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - - + - +### GetLatestValidatorSetResponse +GetLatestValidatorSetResponse is the response type for the Query/GetValidatorSetByHeight RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `block_height` | [int64](#int64) | | | +| `validators` | [Validator](#cosmos.base.tendermint.v1beta1.Validator) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | - -

      Top

      -## cosmos/mint/v1beta1/query.proto - + -### QueryAnnualProvisionsRequest -QueryAnnualProvisionsRequest is the request type for the -Query/AnnualProvisions RPC method. +### GetNodeInfoRequest +GetNodeInfoRequest is the request type for the Query/GetNodeInfo RPC method. - + -### QueryAnnualProvisionsResponse -QueryAnnualProvisionsResponse is the response type for the -Query/AnnualProvisions RPC method. +### GetNodeInfoResponse +GetNodeInfoResponse is the request type for the Query/GetNodeInfo RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `annual_provisions` | [bytes](#bytes) | | annual_provisions is the current minting annual provisions value. | +| `default_node_info` | [tendermint.p2p.DefaultNodeInfo](#tendermint.p2p.DefaultNodeInfo) | | | +| `application_version` | [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) | | | - + -### QueryInflationRequest -QueryInflationRequest is the request type for the Query/Inflation RPC method. +### GetSyncingRequest +GetSyncingRequest is the request type for the Query/GetSyncing RPC method. - + -### QueryInflationResponse -QueryInflationResponse is the response type for the Query/Inflation RPC -method. +### GetSyncingResponse +GetSyncingResponse is the response type for the Query/GetSyncing RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `inflation` | [bytes](#bytes) | | inflation is the current minting inflation value. | - - +| `syncing` | [bool](#bool) | | | - -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. + +### GetValidatorSetByHeightRequest +GetValidatorSetByHeightRequest is the request type for the Query/GetValidatorSetByHeight RPC method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [int64](#int64) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines the parameters of the module. | + +### GetValidatorSetByHeightResponse +GetValidatorSetByHeightResponse is the response type for the Query/GetValidatorSetByHeight RPC method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `block_height` | [int64](#int64) | | | +| `validators` | [Validator](#cosmos.base.tendermint.v1beta1.Validator) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | - - - - -### Query -Query provides defines the gRPC querier service. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Params` | [QueryParamsRequest](#cosmos.mint.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.mint.v1beta1.QueryParamsResponse) | Params returns the total set of minting parameters. | GET|/cosmos/mint/v1beta1/params| -| `Inflation` | [QueryInflationRequest](#cosmos.mint.v1beta1.QueryInflationRequest) | [QueryInflationResponse](#cosmos.mint.v1beta1.QueryInflationResponse) | Inflation returns the current minting inflation value. | GET|/cosmos/mint/v1beta1/inflation| -| `AnnualProvisions` | [QueryAnnualProvisionsRequest](#cosmos.mint.v1beta1.QueryAnnualProvisionsRequest) | [QueryAnnualProvisionsResponse](#cosmos.mint.v1beta1.QueryAnnualProvisionsResponse) | AnnualProvisions current minting annual provisions value. | GET|/cosmos/mint/v1beta1/annual_provisions| +### Module +Module is the type for VersionInfo - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `path` | [string](#string) | | module path | +| `version` | [string](#string) | | module version | +| `sum` | [string](#string) | | checksum | - -

      Top

      -## cosmos/params/v1beta1/params.proto - + -### ParamChange -ParamChange defines an individual parameter change, for use in -ParameterChangeProposal. +### Validator +Validator is the type for the validator-set. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `subspace` | [string](#string) | | | -| `key` | [string](#string) | | | -| `value` | [string](#string) | | | +| `address` | [string](#string) | | | +| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `voting_power` | [int64](#int64) | | | +| `proposer_priority` | [int64](#int64) | | | - + -### ParameterChangeProposal -ParameterChangeProposal defines a proposal to change one or more parameters. +### VersionInfo +VersionInfo is the type for the GetNodeInfoResponse message. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `changes` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | repeated | | +| `name` | [string](#string) | | | +| `app_name` | [string](#string) | | | +| `version` | [string](#string) | | | +| `git_commit` | [string](#string) | | | +| `build_tags` | [string](#string) | | | +| `go_version` | [string](#string) | | | +| `build_deps` | [Module](#cosmos.base.tendermint.v1beta1.Module) | repeated | | @@ -4992,42 +5397,60 @@ ParameterChangeProposal defines a proposal to change one or more parameters. + + + +### Service +Service defines the gRPC querier service for tendermint queries. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `GetNodeInfo` | [GetNodeInfoRequest](#cosmos.base.tendermint.v1beta1.GetNodeInfoRequest) | [GetNodeInfoResponse](#cosmos.base.tendermint.v1beta1.GetNodeInfoResponse) | GetNodeInfo queries the current node info. | GET|/cosmos/base/tendermint/v1beta1/node_info| +| `GetSyncing` | [GetSyncingRequest](#cosmos.base.tendermint.v1beta1.GetSyncingRequest) | [GetSyncingResponse](#cosmos.base.tendermint.v1beta1.GetSyncingResponse) | GetSyncing queries node syncing. | GET|/cosmos/base/tendermint/v1beta1/syncing| +| `GetLatestBlock` | [GetLatestBlockRequest](#cosmos.base.tendermint.v1beta1.GetLatestBlockRequest) | [GetLatestBlockResponse](#cosmos.base.tendermint.v1beta1.GetLatestBlockResponse) | GetLatestBlock returns the latest block. | GET|/cosmos/base/tendermint/v1beta1/blocks/latest| +| `GetBlockByHeight` | [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) | [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) | GetBlockByHeight queries block for given height. | GET|/cosmos/base/tendermint/v1beta1/blocks/{height}| +| `GetLatestValidatorSet` | [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) | [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) | GetLatestValidatorSet queries latest validator-set. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/latest| +| `GetValidatorSetByHeight` | [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) | [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) | GetValidatorSetByHeight queries validator-set at a given height. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/{height}| + - +

      Top

      -## cosmos/params/v1beta1/query.proto +## cosmos/base/snapshots/v1beta1/snapshot.proto - + -### QueryParamsRequest -QueryParamsRequest is request type for the Query/Params RPC method. +### Metadata +Metadata contains SDK-specific snapshot metadata. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `subspace` | [string](#string) | | subspace defines the module to query the parameter for. | -| `key` | [string](#string) | | key defines the key of the parameter in the subspace. | +| `chunk_hashes` | [bytes](#bytes) | repeated | SHA-256 chunk hashes | - + -### QueryParamsResponse -QueryParamsResponse is response type for the Query/Params RPC method. +### Snapshot +Snapshot contains Tendermint state sync snapshot info. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `param` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | | param defines the queried parameter. | +| `height` | [uint64](#uint64) | | | +| `format` | [uint32](#uint32) | | | +| `chunks` | [uint32](#uint32) | | | +| `hash` | [bytes](#bytes) | | | +| `metadata` | [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) | | | @@ -5039,143 +5462,135 @@ QueryParamsResponse is response type for the Query/Params RPC method. - - - -### Query -Query defines the gRPC querier service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Params` | [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) | Params queries a specific parameter of a module, given its subspace and key. | GET|/cosmos/params/v1beta1/params| - - +

      Top

      -## cosmos/slashing/v1beta1/slashing.proto - - - - +## cosmos/base/reflection/v1beta1/reflection.proto -### Params -Params represents the parameters used for by the slashing module. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `signed_blocks_window` | [int64](#int64) | | | -| `min_signed_per_window` | [bytes](#bytes) | | | -| `downtime_jail_duration` | [google.protobuf.Duration](#google.protobuf.Duration) | | | -| `slash_fraction_double_sign` | [bytes](#bytes) | | | -| `slash_fraction_downtime` | [bytes](#bytes) | | | + +### ListAllInterfacesRequest +ListAllInterfacesRequest is the request type of the ListAllInterfaces RPC. - -### ValidatorSigningInfo -ValidatorSigningInfo defines a validator's signing info for monitoring their -liveness activity. + +### ListAllInterfacesResponse +ListAllInterfacesResponse is the response type of the ListAllInterfaces RPC. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `start_height` | [int64](#int64) | | Height at which validator was first a candidate OR was unjailed | -| `index_offset` | [int64](#int64) | | Index which is incremented each time the validator was a bonded in a block and may have signed a precommit or not. This in conjunction with the `SignedBlocksWindow` param determines the index in the `MissedBlocksBitArray`. | -| `jailed_until` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | Timestamp until which the validator is jailed due to liveness downtime. | -| `tombstoned` | [bool](#bool) | | Whether or not a validator has been tombstoned (killed out of validator set). It is set once the validator commits an equivocation or for any other configured misbehiavor. | -| `missed_blocks_counter` | [int64](#int64) | | A counter kept to avoid unnecessary array reads. Note that `Sum(MissedBlocksBitArray)` always equals `MissedBlocksCounter`. | +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `interface_names` | [string](#string) | repeated | interface_names is an array of all the registered interfaces. | - - - + - +### ListImplementationsRequest +ListImplementationsRequest is the request type of the ListImplementations +RPC. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `interface_name` | [string](#string) | | interface_name defines the interface to query the implementations for. | - -

      Top

      -## cosmos/slashing/v1beta1/genesis.proto - -### GenesisState -GenesisState defines the slashing module's genesis state. + + +### ListImplementationsResponse +ListImplementationsResponse is the response type of the ListImplementations +RPC. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.slashing.v1beta1.Params) | | params defines all the paramaters of related to deposit. | -| `signing_infos` | [SigningInfo](#cosmos.slashing.v1beta1.SigningInfo) | repeated | signing_infos represents a map between validator addresses and their signing infos. | -| `missed_blocks` | [ValidatorMissedBlocks](#cosmos.slashing.v1beta1.ValidatorMissedBlocks) | repeated | signing_infos represents a map between validator addresses and their missed blocks. | +| `implementation_message_names` | [string](#string) | repeated | | + - + -### MissedBlock -MissedBlock contains height and missed status as boolean. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `index` | [int64](#int64) | | index is the height at which the block was missed. | -| `missed` | [bool](#bool) | | missed is the missed status. | + +### ReflectionService +ReflectionService defines a service for interface reflection. +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `ListAllInterfaces` | [ListAllInterfacesRequest](#cosmos.base.reflection.v1beta1.ListAllInterfacesRequest) | [ListAllInterfacesResponse](#cosmos.base.reflection.v1beta1.ListAllInterfacesResponse) | ListAllInterfaces lists all the interfaces registered in the interface registry. | GET|/cosmos/base/reflection/v1beta1/interfaces| +| `ListImplementations` | [ListImplementationsRequest](#cosmos.base.reflection.v1beta1.ListImplementationsRequest) | [ListImplementationsResponse](#cosmos.base.reflection.v1beta1.ListImplementationsResponse) | ListImplementations list all the concrete types that implement a given interface. | GET|/cosmos/base/reflection/v1beta1/interfaces/{interface_name}/implementations| + - + +

      Top

      -### SigningInfo -SigningInfo stores validator signing info of corresponding address. +## cosmos/slashing/v1beta1/slashing.proto + + + + + +### Params +Params represents the parameters used for by the slashing module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the validator address. | -| `validator_signing_info` | [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) | | validator_signing_info represents the signing info of this validator. | +| `signed_blocks_window` | [int64](#int64) | | | +| `min_signed_per_window` | [bytes](#bytes) | | | +| `downtime_jail_duration` | [google.protobuf.Duration](#google.protobuf.Duration) | | | +| `slash_fraction_double_sign` | [bytes](#bytes) | | | +| `slash_fraction_downtime` | [bytes](#bytes) | | | - + -### ValidatorMissedBlocks -ValidatorMissedBlocks contains array of missed blocks of corresponding -address. +### ValidatorSigningInfo +ValidatorSigningInfo defines a validator's signing info for monitoring their +liveness activity. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the validator address. | -| `missed_blocks` | [MissedBlock](#cosmos.slashing.v1beta1.MissedBlock) | repeated | missed_blocks is an array of missed blocks by the validator. | +| `address` | [string](#string) | | | +| `start_height` | [int64](#int64) | | Height at which validator was first a candidate OR was unjailed | +| `index_offset` | [int64](#int64) | | Index which is incremented each time the validator was a bonded in a block and may have signed a precommit or not. This in conjunction with the `SignedBlocksWindow` param determines the index in the `MissedBlocksBitArray`. | +| `jailed_until` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | Timestamp until which the validator is jailed due to liveness downtime. | +| `tombstoned` | [bool](#bool) | | Whether or not a validator has been tombstoned (killed out of validator set). It is set once the validator commits an equivocation or for any other configured misbehiavor. | +| `missed_blocks_counter` | [int64](#int64) | | A counter kept to avoid unnecessary array reads. Note that `Sum(MissedBlocksBitArray)` always equals `MissedBlocksCounter`. | @@ -5360,375 +5775,430 @@ Msg defines the slashing Msg service. - +

      Top

      -## cosmos/staking/v1beta1/staking.proto +## cosmos/slashing/v1beta1/genesis.proto - + -### Commission -Commission defines commission parameters for a given validator. +### GenesisState +GenesisState defines the slashing module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `commission_rates` | [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) | | | -| `update_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `params` | [Params](#cosmos.slashing.v1beta1.Params) | | params defines all the paramaters of related to deposit. | +| `signing_infos` | [SigningInfo](#cosmos.slashing.v1beta1.SigningInfo) | repeated | signing_infos represents a map between validator addresses and their signing infos. | +| `missed_blocks` | [ValidatorMissedBlocks](#cosmos.slashing.v1beta1.ValidatorMissedBlocks) | repeated | signing_infos represents a map between validator addresses and their missed blocks. | - + -### CommissionRates -CommissionRates defines the initial commission rates to be used for creating -a validator. +### MissedBlock +MissedBlock contains height and missed status as boolean. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `rate` | [string](#string) | | | -| `max_rate` | [string](#string) | | | -| `max_change_rate` | [string](#string) | | | +| `index` | [int64](#int64) | | index is the height at which the block was missed. | +| `missed` | [bool](#bool) | | missed is the missed status. | - + -### DVPair -DVPair is struct that just has a delegator-validator pair with no other data. -It is intended to be used as a marshalable pointer. For example, a DVPair can -be used to construct the key to getting an UnbondingDelegation from state. +### SigningInfo +SigningInfo stores validator signing info of corresponding address. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | +| `address` | [string](#string) | | address is the validator address. | +| `validator_signing_info` | [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) | | validator_signing_info represents the signing info of this validator. | - + -### DVPairs -DVPairs defines an array of DVPair objects. +### ValidatorMissedBlocks +ValidatorMissedBlocks contains array of missed blocks of corresponding +address. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pairs` | [DVPair](#cosmos.staking.v1beta1.DVPair) | repeated | | +| `address` | [string](#string) | | address is the validator address. | +| `missed_blocks` | [MissedBlock](#cosmos.slashing.v1beta1.MissedBlock) | repeated | missed_blocks is an array of missed blocks by the validator. | + - + + + + + -### DVVTriplet -DVVTriplet is struct that just has a delegator-validator-validator triplet -with no other data. It is intended to be used as a marshalable pointer. For -example, a DVVTriplet can be used to construct the key to getting a -Redelegation from state. + + + +

      Top

      + +## cosmos/evidence/v1beta1/evidence.proto + + + + + +### Equivocation +Equivocation implements the Evidence interface and defines evidence of double +signing misbehavior. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_src_address` | [string](#string) | | | -| `validator_dst_address` | [string](#string) | | | +| `height` | [int64](#int64) | | | +| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `power` | [int64](#int64) | | | +| `consensus_address` | [string](#string) | | | + - + -### DVVTriplets -DVVTriplets defines an array of DVVTriplet objects. + + + + + + + +

      Top

      + +## cosmos/evidence/v1beta1/query.proto + + + + + +### QueryAllEvidenceRequest +QueryEvidenceRequest is the request type for the Query/AllEvidence RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `triplets` | [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - + -### Delegation -Delegation represents the bond with tokens held by an account. It is -owned by one delegator, and is associated with the voting power of one -validator. +### QueryAllEvidenceResponse +QueryAllEvidenceResponse is the response type for the Query/AllEvidence RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | -| `shares` | [string](#string) | | | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence returns all evidences. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | + + + + + + + + +### QueryEvidenceRequest +QueryEvidenceRequest is the request type for the Query/Evidence RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `evidence_hash` | [bytes](#bytes) | | evidence_hash defines the hash of the requested evidence. | + + + + + + + + +### QueryEvidenceResponse +QueryEvidenceResponse is the response type for the Query/Evidence RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | evidence returns the requested evidence. | + + + + + + + + + + + + + + +### Query +Query defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Evidence` | [QueryEvidenceRequest](#cosmos.evidence.v1beta1.QueryEvidenceRequest) | [QueryEvidenceResponse](#cosmos.evidence.v1beta1.QueryEvidenceResponse) | Evidence queries evidence based on evidence hash. | GET|/cosmos/evidence/v1beta1/evidence/{evidence_hash}| +| `AllEvidence` | [QueryAllEvidenceRequest](#cosmos.evidence.v1beta1.QueryAllEvidenceRequest) | [QueryAllEvidenceResponse](#cosmos.evidence.v1beta1.QueryAllEvidenceResponse) | AllEvidence queries all evidence. | GET|/cosmos/evidence/v1beta1/evidence| + + + +

      Top

      +## cosmos/evidence/v1beta1/tx.proto - -### DelegationResponse -DelegationResponse is equivalent to Delegation except that it contains a -balance in addition to shares which is more suitable for client responses. + + +### MsgSubmitEvidence +MsgSubmitEvidence represents a message that supports submitting arbitrary +Evidence of misbehavior such as equivocation or counterfactual signing. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegation` | [Delegation](#cosmos.staking.v1beta1.Delegation) | | | -| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | +| `submitter` | [string](#string) | | | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | | - + -### Description -Description defines a validator description. +### MsgSubmitEvidenceResponse +MsgSubmitEvidenceResponse defines the Msg/SubmitEvidence response type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `moniker` | [string](#string) | | | -| `identity` | [string](#string) | | | -| `website` | [string](#string) | | | -| `security_contact` | [string](#string) | | | -| `details` | [string](#string) | | | +| `hash` | [bytes](#bytes) | | hash defines the hash of the evidence. | + - + -### HistoricalInfo -HistoricalInfo contains header and validator information for a given block. -It is stored as part of staking module's state, which persists the `n` most -recent HistoricalInfo -(`n` is set by the staking module's `historical_entries` parameter). + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `header` | [tendermint.types.Header](#tendermint.types.Header) | | | -| `valset` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | | + + +### Msg +Msg defines the evidence Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `SubmitEvidence` | [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) | [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) | SubmitEvidence submits an arbitrary Evidence of misbehavior such as equivocation or counterfactual signing. | | + + +

      Top

      +## cosmos/evidence/v1beta1/genesis.proto - -### Params -Params defines the parameters for the staking module. + + + +### GenesisState +GenesisState defines the evidence module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `unbonding_time` | [google.protobuf.Duration](#google.protobuf.Duration) | | | -| `max_validators` | [uint32](#uint32) | | | -| `max_entries` | [uint32](#uint32) | | | -| `historical_entries` | [uint32](#uint32) | | | -| `bond_denom` | [string](#string) | | | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence defines all the evidence at genesis. | + - + -### Pool -Pool is used for tracking bonded and not-bonded token supply of the bond -denomination. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `not_bonded_tokens` | [string](#string) | | | -| `bonded_tokens` | [string](#string) | | | + +

      Top

      +## cosmos/auth/v1beta1/auth.proto - + -### Redelegation -Redelegation contains the list of a particular delegator's redelegating bonds -from a particular source validator to a particular destination validator. +### BaseAccount +BaseAccount defines a base account type. It contains all the necessary fields +for basic account functionality. Any custom account type should extend this +type for additional functionality (e.g. vesting). | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_src_address` | [string](#string) | | | -| `validator_dst_address` | [string](#string) | | | -| `entries` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | repeated | redelegation entries | +| `address` | [string](#string) | | | +| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `account_number` | [uint64](#uint64) | | | +| `sequence` | [uint64](#uint64) | | | - + -### RedelegationEntry -RedelegationEntry defines a redelegation object with relevant metadata. +### ModuleAccount +ModuleAccount defines an account for modules that holds coins on a pool. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `creation_height` | [int64](#int64) | | | -| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `initial_balance` | [string](#string) | | | -| `shares_dst` | [string](#string) | | | +| `base_account` | [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) | | | +| `name` | [string](#string) | | | +| `permissions` | [string](#string) | repeated | | - + -### RedelegationEntryResponse -RedelegationEntryResponse is equivalent to a RedelegationEntry except that it -contains a balance in addition to shares which is more suitable for client -responses. +### Params +Params defines the parameters for the auth module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `redelegation_entry` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | | | -| `balance` | [string](#string) | | | +| `max_memo_characters` | [uint64](#uint64) | | | +| `tx_sig_limit` | [uint64](#uint64) | | | +| `tx_size_cost_per_byte` | [uint64](#uint64) | | | +| `sig_verify_cost_ed25519` | [uint64](#uint64) | | | +| `sig_verify_cost_secp256k1` | [uint64](#uint64) | | | + - + -### RedelegationResponse -RedelegationResponse is equivalent to a Redelegation except that its entries -contain a balance in addition to shares which is more suitable for client -responses. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `redelegation` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | | | -| `entries` | [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) | repeated | | + +

      Top

      +## cosmos/auth/v1beta1/query.proto - + -### UnbondingDelegation -UnbondingDelegation stores all of a single delegator's unbonding bonds -for a single validator in an time-ordered list. +### QueryAccountRequest +QueryAccountRequest is the request type for the Query/Account RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | -| `entries` | [UnbondingDelegationEntry](#cosmos.staking.v1beta1.UnbondingDelegationEntry) | repeated | unbonding delegation entries | +| `address` | [string](#string) | | address defines the address to query for. | - + -### UnbondingDelegationEntry -UnbondingDelegationEntry defines an unbonding object with relevant metadata. +### QueryAccountResponse +QueryAccountResponse is the response type for the Query/Account RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `creation_height` | [int64](#int64) | | | -| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `initial_balance` | [string](#string) | | | -| `balance` | [string](#string) | | | - - +| `account` | [google.protobuf.Any](#google.protobuf.Any) | | account defines the account of the corresponding address. | - -### ValAddresses -ValAddresses defines a repeated set of validator addresses. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `addresses` | [string](#string) | repeated | | +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. - + -### Validator -Validator defines a validator, together with the total amount of the -Validator's bond shares and their exchange rate to coins. Slashing results in -a decrease in the exchange rate, allowing correct calculation of future -undelegations without iterating over delegators. When coins are delegated to -this validator, the validator is credited with a delegation whose number of -bond shares is based on the amount of coins delegated divided by the current -exchange rate. Voting power can be calculated as total bonded shares -multiplied by exchange rate. +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `operator_address` | [string](#string) | | | -| `consensus_pubkey` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `jailed` | [bool](#bool) | | | -| `status` | [BondStatus](#cosmos.staking.v1beta1.BondStatus) | | | -| `tokens` | [string](#string) | | | -| `delegator_shares` | [string](#string) | | | -| `description` | [Description](#cosmos.staking.v1beta1.Description) | | | -| `unbonding_height` | [int64](#int64) | | | -| `unbonding_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `commission` | [Commission](#cosmos.staking.v1beta1.Commission) | | | -| `min_self_delegation` | [string](#string) | | | +| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines the parameters of the module. | @@ -5736,67 +6206,42 @@ multiplied by exchange rate. + - - -### BondStatus -BondStatus is the status of a validator. + -| Name | Number | Description | -| ---- | ------ | ----------- | -| BOND_STATUS_UNSPECIFIED | 0 | UNSPECIFIED defines an invalid validator status. | -| BOND_STATUS_UNBONDED | 1 | UNBONDED defines a validator that is not bonded. | -| BOND_STATUS_UNBONDING | 2 | UNBONDING defines a validator that is unbonding. | -| BOND_STATUS_BONDED | 3 | BONDED defines a validator that is bonded. | + - +### Query +Query defines the gRPC querier service. - +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Account` | [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) | [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) | Account returns account details based on address. | GET|/cosmos/auth/v1beta1/accounts/{address}| +| `Params` | [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) | Params queries all parameters. | GET|/cosmos/auth/v1beta1/params| - +

      Top

      -## cosmos/staking/v1beta1/genesis.proto +## cosmos/auth/v1beta1/genesis.proto - + ### GenesisState -GenesisState defines the staking module's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.staking.v1beta1.Params) | | params defines all the paramaters of related to deposit. | -| `last_total_power` | [bytes](#bytes) | | last_total_power tracks the total amounts of bonded tokens recorded during the previous end block. | -| `last_validator_powers` | [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) | repeated | last_validator_powers is a special index that provides a historical list of the last-block's bonded validators. | -| `validators` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | delegations defines the validator set at genesis. | -| `delegations` | [Delegation](#cosmos.staking.v1beta1.Delegation) | repeated | delegations defines the delegations active at genesis. | -| `unbonding_delegations` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | repeated | unbonding_delegations defines the unbonding delegations active at genesis. | -| `redelegations` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | repeated | redelegations defines the redelegations active at genesis. | -| `exported` | [bool](#bool) | | | - - - - - - - - -### LastValidatorPower -LastValidatorPower required for validator set update logic. +GenesisState defines the auth module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the address of the validator. | -| `power` | [int64](#int64) | | power defines the power of the validator. | +| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines all the paramaters of the module. | +| `accounts` | [google.protobuf.Any](#google.protobuf.Any) | repeated | accounts are the accounts present at genesis. | @@ -6298,483 +6743,229 @@ Query defines the gRPC querier service. - -

      Top

      - -## cosmos/staking/v1beta1/tx.proto - - - - - -### MsgBeginRedelegate -MsgBeginRedelegate defines a SDK message for performing a redelegation -of coins from a delegator and source validator to a destination validator. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_src_address` | [string](#string) | | | -| `validator_dst_address` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - - - - - - - - -### MsgBeginRedelegateResponse -MsgBeginRedelegateResponse defines the Msg/BeginRedelegate response type. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - - - - - - - - -### MsgCreateValidator -MsgCreateValidator defines a SDK message for creating a new validator. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `description` | [Description](#cosmos.staking.v1beta1.Description) | | | -| `commission` | [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) | | | -| `min_self_delegation` | [string](#string) | | | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | -| `pubkey` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `value` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - - - - - - - - -### MsgCreateValidatorResponse -MsgCreateValidatorResponse defines the Msg/CreateValidator response type. - - - - - - - - -### MsgDelegate -MsgDelegate defines a SDK message for performing a delegation of coins -from a delegator to a validator. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - - - - - - - - -### MsgDelegateResponse -MsgDelegateResponse defines the Msg/Delegate response type. - - - - - - - - -### MsgEditValidator -MsgEditValidator defines a SDK message for editing an existing validator. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `description` | [Description](#cosmos.staking.v1beta1.Description) | | | -| `validator_address` | [string](#string) | | | -| `commission_rate` | [string](#string) | | We pass a reference to the new commission rate and min self delegation as it's not mandatory to update. If not updated, the deserialized rate will be zero with no way to distinguish if an update was intended. REF: #2373 | -| `min_self_delegation` | [string](#string) | | | - - - - - - - - -### MsgEditValidatorResponse -MsgEditValidatorResponse defines the Msg/EditValidator response type. - - - - - - - - -### MsgUndelegate -MsgUndelegate defines a SDK message for performing an undelegation from a -delegate and a validator. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - - - - - - - - -### MsgUndelegateResponse -MsgUndelegateResponse defines the Msg/Undelegate response type. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - - - - - - - - - - - - - - -### Msg -Msg defines the staking Msg service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `CreateValidator` | [MsgCreateValidator](#cosmos.staking.v1beta1.MsgCreateValidator) | [MsgCreateValidatorResponse](#cosmos.staking.v1beta1.MsgCreateValidatorResponse) | CreateValidator defines a method for creating a new validator. | | -| `EditValidator` | [MsgEditValidator](#cosmos.staking.v1beta1.MsgEditValidator) | [MsgEditValidatorResponse](#cosmos.staking.v1beta1.MsgEditValidatorResponse) | EditValidator defines a method for editing an existing validator. | | -| `Delegate` | [MsgDelegate](#cosmos.staking.v1beta1.MsgDelegate) | [MsgDelegateResponse](#cosmos.staking.v1beta1.MsgDelegateResponse) | Delegate defines a method for performing a delegation of coins from a delegator to a validator. | | -| `BeginRedelegate` | [MsgBeginRedelegate](#cosmos.staking.v1beta1.MsgBeginRedelegate) | [MsgBeginRedelegateResponse](#cosmos.staking.v1beta1.MsgBeginRedelegateResponse) | BeginRedelegate defines a method for performing a redelegation of coins from a delegator and source validator to a destination validator. | | -| `Undelegate` | [MsgUndelegate](#cosmos.staking.v1beta1.MsgUndelegate) | [MsgUndelegateResponse](#cosmos.staking.v1beta1.MsgUndelegateResponse) | Undelegate defines a method for performing an undelegation from a delegate and a validator. | | - - - - - - -

      Top

      - -## cosmos/tx/signing/v1beta1/signing.proto - - - - - -### SignatureDescriptor -SignatureDescriptor is a convenience type which represents the full data for -a signature including the public key of the signer, signing modes and the -signature itself. It is primarily used for coordinating signatures between -clients. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public_key is the public key of the signer | -| `data` | [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) | | | -| `sequence` | [uint64](#uint64) | | sequence is the sequence of the account, which describes the number of committed transactions signed by a given address. It is used to prevent replay attacks. | - - - - - - - - -### SignatureDescriptor.Data -Data represents signature data - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `single` | [SignatureDescriptor.Data.Single](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Single) | | single represents a single signer | -| `multi` | [SignatureDescriptor.Data.Multi](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Multi) | | multi represents a multisig signer | - - - - - - - - -### SignatureDescriptor.Data.Multi -Multi is the signature data for a multisig public key - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `bitarray` | [cosmos.crypto.multisig.v1beta1.CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) | | bitarray specifies which keys within the multisig are signing | -| `signatures` | [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) | repeated | signatures is the signatures of the multi-signature | - - - - - - - - -### SignatureDescriptor.Data.Single -Single is the signature data for a single signer - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `mode` | [SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | -| `signature` | [bytes](#bytes) | | signature is the raw signature bytes | - - + +

      Top

      +## cosmos/staking/v1beta1/tx.proto - + -### SignatureDescriptors -SignatureDescriptors wraps multiple SignatureDescriptor's. +### MsgBeginRedelegate +MsgBeginRedelegate defines a SDK message for performing a redelegation +of coins from a delegator and source validator to a destination validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `signatures` | [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) | repeated | signatures are the signature descriptors | +| `delegator_address` | [string](#string) | | | +| `validator_src_address` | [string](#string) | | | +| `validator_dst_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - + - +### MsgBeginRedelegateResponse +MsgBeginRedelegateResponse defines the Msg/BeginRedelegate response type. -### SignMode -SignMode represents a signing mode with its own security guarantees. -| Name | Number | Description | -| ---- | ------ | ----------- | -| SIGN_MODE_UNSPECIFIED | 0 | SIGN_MODE_UNSPECIFIED specifies an unknown signing mode and will be rejected | -| SIGN_MODE_DIRECT | 1 | SIGN_MODE_DIRECT specifies a signing mode which uses SignDoc and is verified with raw bytes from Tx | -| SIGN_MODE_TEXTUAL | 2 | SIGN_MODE_TEXTUAL is a future signing mode that will verify some human-readable textual representation on top of the binary representation from SIGN_MODE_DIRECT | -| SIGN_MODE_LEGACY_AMINO_JSON | 127 | SIGN_MODE_LEGACY_AMINO_JSON is a backwards compatibility mode which uses Amino JSON and will be removed in the future | +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - - - + - -

      Top

      +### MsgCreateValidator +MsgCreateValidator defines a SDK message for creating a new validator. -## cosmos/tx/v1beta1/tx.proto +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `description` | [Description](#cosmos.staking.v1beta1.Description) | | | +| `commission` | [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) | | | +| `min_self_delegation` | [string](#string) | | | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | +| `pubkey` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `value` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - -### AuthInfo -AuthInfo describes the fee and signer modes that are used to sign a -transaction. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `signer_infos` | [SignerInfo](#cosmos.tx.v1beta1.SignerInfo) | repeated | signer_infos defines the signing modes for the required signers. The number and order of elements must match the required signers from TxBody's messages. The first element is the primary signer and the one which pays the fee. | -| `fee` | [Fee](#cosmos.tx.v1beta1.Fee) | | Fee is the fee and gas limit for the transaction. The first signer is the primary signer and the one which pays the fee. The fee can be calculated based on the cost of evaluating the body and doing signature verification of the signers. This can be estimated via simulation. | + +### MsgCreateValidatorResponse +MsgCreateValidatorResponse defines the Msg/CreateValidator response type. - -### Fee -Fee includes the amount of coins paid in fees and the maximum -gas to be used by the transaction. The ratio yields an effective "gasprice", -which must be above some miminum to be accepted into the mempool. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | amount is the amount of coins to be paid as a fee | -| `gas_limit` | [uint64](#uint64) | | gas_limit is the maximum gas that can be used in transaction processing before an out of gas error occurs | -| `payer` | [string](#string) | | if unset, the first signer is responsible for paying the fees. If set, the specified account must pay the fees. the payer must be a tx signer (and thus have signed this field in AuthInfo). setting this field does *not* change the ordering of required signers for the transaction. | -| `granter` | [string](#string) | | if set, the fee payer (either the first signer or the value of the payer field) requests that a fee grant be used to pay fees instead of the fee payer's own balance. If an appropriate fee grant does not exist or the chain does not support fee grants, this will fail | +### MsgDelegate +MsgDelegate defines a SDK message for performing a delegation of coins +from a delegator to a validator. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - -### ModeInfo -ModeInfo describes the signing mode of a single or nested multisig signer. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `single` | [ModeInfo.Single](#cosmos.tx.v1beta1.ModeInfo.Single) | | single represents a single signer | -| `multi` | [ModeInfo.Multi](#cosmos.tx.v1beta1.ModeInfo.Multi) | | multi represents a nested multisig signer | +### MsgDelegateResponse +MsgDelegateResponse defines the Msg/Delegate response type. - + -### ModeInfo.Multi -Multi is the mode info for a multisig public key +### MsgEditValidator +MsgEditValidator defines a SDK message for editing an existing validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `bitarray` | [cosmos.crypto.multisig.v1beta1.CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) | | bitarray specifies which keys within the multisig are signing | -| `mode_infos` | [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) | repeated | mode_infos is the corresponding modes of the signers of the multisig which could include nested multisig public keys | - - +| `description` | [Description](#cosmos.staking.v1beta1.Description) | | | +| `validator_address` | [string](#string) | | | +| `commission_rate` | [string](#string) | | We pass a reference to the new commission rate and min self delegation as it's not mandatory to update. If not updated, the deserialized rate will be zero with no way to distinguish if an update was intended. REF: #2373 | +| `min_self_delegation` | [string](#string) | | | - -### ModeInfo.Single -Single is the mode info for a single signer. It is structured as a message -to allow for additional fields such as locale for SIGN_MODE_TEXTUAL in the -future + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `mode` | [cosmos.tx.signing.v1beta1.SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | +### MsgEditValidatorResponse +MsgEditValidatorResponse defines the Msg/EditValidator response type. - + -### SignDoc -SignDoc is the type used for generating sign bytes for SIGN_MODE_DIRECT. +### MsgUndelegate +MsgUndelegate defines a SDK message for performing an undelegation from a +delegate and a validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `body_bytes` | [bytes](#bytes) | | body_bytes is protobuf serialization of a TxBody that matches the representation in TxRaw. | -| `auth_info_bytes` | [bytes](#bytes) | | auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in TxRaw. | -| `chain_id` | [string](#string) | | chain_id is the unique identifier of the chain this transaction targets. It prevents signed transactions from being used on another chain by an attacker | -| `account_number` | [uint64](#uint64) | | account_number is the account number of the account in state | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - + -### SignerInfo -SignerInfo describes the public key and signing mode of a single top-level -signer. +### MsgUndelegateResponse +MsgUndelegateResponse defines the Msg/Undelegate response type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public_key is the public key of the signer. It is optional for accounts that already exist in state. If unset, the verifier can use the required \ signer address for this position and lookup the public key. | -| `mode_info` | [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) | | mode_info describes the signing mode of the signer and is a nested structure to support nested multisig pubkey's | -| `sequence` | [uint64](#uint64) | | sequence is the sequence of the account, which describes the number of committed transactions signed by a given address. It is used to prevent replay attacks. | +| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | + - + -### Tx -Tx is the standard type used for broadcasting transactions. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `body` | [TxBody](#cosmos.tx.v1beta1.TxBody) | | body is the processable content of the transaction | -| `auth_info` | [AuthInfo](#cosmos.tx.v1beta1.AuthInfo) | | auth_info is the authorization related content of the transaction, specifically signers, signer modes and fee | -| `signatures` | [bytes](#bytes) | repeated | signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to allow connecting signature meta information like public key and signing mode by position. | + + +### Msg +Msg defines the staking Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `CreateValidator` | [MsgCreateValidator](#cosmos.staking.v1beta1.MsgCreateValidator) | [MsgCreateValidatorResponse](#cosmos.staking.v1beta1.MsgCreateValidatorResponse) | CreateValidator defines a method for creating a new validator. | | +| `EditValidator` | [MsgEditValidator](#cosmos.staking.v1beta1.MsgEditValidator) | [MsgEditValidatorResponse](#cosmos.staking.v1beta1.MsgEditValidatorResponse) | EditValidator defines a method for editing an existing validator. | | +| `Delegate` | [MsgDelegate](#cosmos.staking.v1beta1.MsgDelegate) | [MsgDelegateResponse](#cosmos.staking.v1beta1.MsgDelegateResponse) | Delegate defines a method for performing a delegation of coins from a delegator to a validator. | | +| `BeginRedelegate` | [MsgBeginRedelegate](#cosmos.staking.v1beta1.MsgBeginRedelegate) | [MsgBeginRedelegateResponse](#cosmos.staking.v1beta1.MsgBeginRedelegateResponse) | BeginRedelegate defines a method for performing a redelegation of coins from a delegator and source validator to a destination validator. | | +| `Undelegate` | [MsgUndelegate](#cosmos.staking.v1beta1.MsgUndelegate) | [MsgUndelegateResponse](#cosmos.staking.v1beta1.MsgUndelegateResponse) | Undelegate defines a method for performing an undelegation from a delegate and a validator. | | + + +

      Top

      +## cosmos/staking/v1beta1/genesis.proto - -### TxBody -TxBody is the body of a transaction that all signers sign over. + + + +### GenesisState +GenesisState defines the staking module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `messages` | [google.protobuf.Any](#google.protobuf.Any) | repeated | messages is a list of messages to be executed. The required signers of those messages define the number and order of elements in AuthInfo's signer_infos and Tx's signatures. Each required signer address is added to the list only the first time it occurs. By convention, the first required signer (usually from the first message) is referred to as the primary signer and pays the fee for the whole transaction. | -| `memo` | [string](#string) | | memo is any arbitrary memo to be added to the transaction | -| `timeout_height` | [uint64](#uint64) | | timeout is the block height after which this transaction will not be processed by the chain | -| `extension_options` | [google.protobuf.Any](#google.protobuf.Any) | repeated | extension_options are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, the transaction will be rejected | -| `non_critical_extension_options` | [google.protobuf.Any](#google.protobuf.Any) | repeated | extension_options are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, they will be ignored | +| `params` | [Params](#cosmos.staking.v1beta1.Params) | | params defines all the paramaters of related to deposit. | +| `last_total_power` | [bytes](#bytes) | | last_total_power tracks the total amounts of bonded tokens recorded during the previous end block. | +| `last_validator_powers` | [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) | repeated | last_validator_powers is a special index that provides a historical list of the last-block's bonded validators. | +| `validators` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | delegations defines the validator set at genesis. | +| `delegations` | [Delegation](#cosmos.staking.v1beta1.Delegation) | repeated | delegations defines the delegations active at genesis. | +| `unbonding_delegations` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | repeated | unbonding_delegations defines the unbonding delegations active at genesis. | +| `redelegations` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | repeated | redelegations defines the redelegations active at genesis. | +| `exported` | [bool](#bool) | | | - + -### TxRaw -TxRaw is a variant of Tx that pins the signer's exact binary representation -of body and auth_info. This is used for signing, broadcasting and -verification. The binary `serialize(tx: TxRaw)` is stored in Tendermint and -the hash `sha256(serialize(tx: TxRaw))` becomes the "txhash", commonly used -as the transaction ID. +### LastValidatorPower +LastValidatorPower required for validator set update logic. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `body_bytes` | [bytes](#bytes) | | body_bytes is a protobuf serialization of a TxBody that matches the representation in SignDoc. | -| `auth_info_bytes` | [bytes](#bytes) | | auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in SignDoc. | -| `signatures` | [bytes](#bytes) | repeated | signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to allow connecting signature meta information like public key and signing mode by position. | +| `address` | [string](#string) | | address is the address of the validator. | +| `power` | [int64](#int64) | | power defines the power of the validator. | @@ -6790,344 +6981,375 @@ as the transaction ID. - +

      Top

      -## cosmos/tx/v1beta1/service.proto +## cosmos/staking/v1beta1/staking.proto - + -### BroadcastTxRequest -BroadcastTxRequest is the request type for the Service.BroadcastTxRequest -RPC method. +### Commission +Commission defines commission parameters for a given validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `tx_bytes` | [bytes](#bytes) | | tx_bytes is the raw transaction. | -| `mode` | [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) | | | +| `commission_rates` | [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) | | | +| `update_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - + -### BroadcastTxResponse -BroadcastTxResponse is the response type for the -Service.BroadcastTx method. +### CommissionRates +CommissionRates defines the initial commission rates to be used for creating +a validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | +| `rate` | [string](#string) | | | +| `max_rate` | [string](#string) | | | +| `max_change_rate` | [string](#string) | | | - + -### GetTxRequest -GetTxRequest is the request type for the Service.GetTx -RPC method. +### DVPair +DVPair is struct that just has a delegator-validator pair with no other data. +It is intended to be used as a marshalable pointer. For example, a DVPair can +be used to construct the key to getting an UnbondingDelegation from state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `hash` | [string](#string) | | hash is the tx hash to query, encoded as a hex string. | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | - + -### GetTxResponse -GetTxResponse is the response type for the Service.GetTx method. +### DVPairs +DVPairs defines an array of DVPair objects. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the queried transaction. | -| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | +| `pairs` | [DVPair](#cosmos.staking.v1beta1.DVPair) | repeated | | - + -### GetTxsEventRequest -GetTxsEventRequest is the request type for the Service.TxsByEvents -RPC method. +### DVVTriplet +DVVTriplet is struct that just has a delegator-validator-validator triplet +with no other data. It is intended to be used as a marshalable pointer. For +example, a DVVTriplet can be used to construct the key to getting a +Redelegation from state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `events` | [string](#string) | repeated | events is the list of transaction event type. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | +| `delegator_address` | [string](#string) | | | +| `validator_src_address` | [string](#string) | | | +| `validator_dst_address` | [string](#string) | | | - + -### GetTxsEventResponse -GetTxsEventResponse is the response type for the Service.TxsByEvents -RPC method. +### DVVTriplets +DVVTriplets defines an array of DVVTriplet objects. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `txs` | [Tx](#cosmos.tx.v1beta1.Tx) | repeated | txs is the list of queried transactions. | -| `tx_responses` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | tx_responses is the list of queried TxResponses. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | +| `triplets` | [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) | repeated | | - + -### SimulateRequest -SimulateRequest is the request type for the Service.Simulate -RPC method. +### Delegation +Delegation represents the bond with tokens held by an account. It is +owned by one delegator, and is associated with the voting power of one +validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the transaction to simulate. | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | +| `shares` | [string](#string) | | | - + -### SimulateResponse -SimulateResponse is the response type for the -Service.SimulateRPC method. +### DelegationResponse +DelegationResponse is equivalent to Delegation except that it contains a +balance in addition to shares which is more suitable for client responses. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `gas_info` | [cosmos.base.abci.v1beta1.GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | gas_info is the information about gas used in the simulation. | -| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | result is the result of the simulation. | +| `delegation` | [Delegation](#cosmos.staking.v1beta1.Delegation) | | | +| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - + - +### Description +Description defines a validator description. -### BroadcastMode -BroadcastMode specifies the broadcast mode for the TxService.Broadcast RPC method. -| Name | Number | Description | -| ---- | ------ | ----------- | -| BROADCAST_MODE_UNSPECIFIED | 0 | zero-value for mode ordering | -| BROADCAST_MODE_BLOCK | 1 | BROADCAST_MODE_BLOCK defines a tx broadcasting mode where the client waits for the tx to be committed in a block. | -| BROADCAST_MODE_SYNC | 2 | BROADCAST_MODE_SYNC defines a tx broadcasting mode where the client waits for a CheckTx execution response only. | -| BROADCAST_MODE_ASYNC | 3 | BROADCAST_MODE_ASYNC defines a tx broadcasting mode where the client returns immediately. | +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `moniker` | [string](#string) | | | +| `identity` | [string](#string) | | | +| `website` | [string](#string) | | | +| `security_contact` | [string](#string) | | | +| `details` | [string](#string) | | | - - - -### Service -Service defines a gRPC service for interacting with transactions. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Simulate` | [SimulateRequest](#cosmos.tx.v1beta1.SimulateRequest) | [SimulateResponse](#cosmos.tx.v1beta1.SimulateResponse) | Simulate simulates executing a transaction for estimating gas usage. | POST|/cosmos/tx/v1beta1/simulate| -| `GetTx` | [GetTxRequest](#cosmos.tx.v1beta1.GetTxRequest) | [GetTxResponse](#cosmos.tx.v1beta1.GetTxResponse) | GetTx fetches a tx by hash. | GET|/cosmos/tx/v1beta1/txs/{hash}| -| `BroadcastTx` | [BroadcastTxRequest](#cosmos.tx.v1beta1.BroadcastTxRequest) | [BroadcastTxResponse](#cosmos.tx.v1beta1.BroadcastTxResponse) | BroadcastTx broadcast transaction. | POST|/cosmos/tx/v1beta1/txs| -| `GetTxsEvent` | [GetTxsEventRequest](#cosmos.tx.v1beta1.GetTxsEventRequest) | [GetTxsEventResponse](#cosmos.tx.v1beta1.GetTxsEventResponse) | GetTxsEvent fetches txs by event. | GET|/cosmos/tx/v1beta1/txs| +### HistoricalInfo +HistoricalInfo contains header and validator information for a given block. +It is stored as part of staking module's state, which persists the `n` most +recent HistoricalInfo +(`n` is set by the staking module's `historical_entries` parameter). - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `header` | [tendermint.types.Header](#tendermint.types.Header) | | | +| `valset` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | | - -

      Top

      -## cosmos/upgrade/v1beta1/upgrade.proto - + -### CancelSoftwareUpgradeProposal -CancelSoftwareUpgradeProposal is a gov Content type for cancelling a software -upgrade. +### Params +Params defines the parameters for the staking module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | +| `unbonding_time` | [google.protobuf.Duration](#google.protobuf.Duration) | | | +| `max_validators` | [uint32](#uint32) | | | +| `max_entries` | [uint32](#uint32) | | | +| `historical_entries` | [uint32](#uint32) | | | +| `bond_denom` | [string](#string) | | | - + -### Plan -Plan specifies information about a planned upgrade and when it should occur. +### Pool +Pool is used for tracking bonded and not-bonded token supply of the bond +denomination. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | Sets the name for the upgrade. This name will be used by the upgraded version of the software to apply any special "on-upgrade" commands during the first BeginBlock method after the upgrade is applied. It is also used to detect whether a software version can handle a given upgrade. If no upgrade handler with this name has been set in the software, it will be assumed that the software is out-of-date when the upgrade Time or Height is reached and the software will exit. | -| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | The time after which the upgrade must be performed. Leave set to its zero value to use a pre-defined Height instead. | -| `height` | [int64](#int64) | | The height at which the upgrade must be performed. Only used if Time is not set. | -| `info` | [string](#string) | | Any application specific upgrade info to be included on-chain such as a git commit that validators could automatically upgrade to | -| `upgraded_client_state` | [google.protobuf.Any](#google.protobuf.Any) | | IBC-enabled chains can opt-in to including the upgraded client state in its upgrade plan This will make the chain commit to the correct upgraded (self) client state before the upgrade occurs, so that connecting chains can verify that the new upgraded client is valid by verifying a proof on the previous version of the chain. This will allow IBC connections to persist smoothly across planned chain upgrades | +| `not_bonded_tokens` | [string](#string) | | | +| `bonded_tokens` | [string](#string) | | | - + -### SoftwareUpgradeProposal -SoftwareUpgradeProposal is a gov Content type for initiating a software -upgrade. +### Redelegation +Redelegation contains the list of a particular delegator's redelegating bonds +from a particular source validator to a particular destination validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | | +| `delegator_address` | [string](#string) | | | +| `validator_src_address` | [string](#string) | | | +| `validator_dst_address` | [string](#string) | | | +| `entries` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | repeated | redelegation entries | - - + - +### RedelegationEntry +RedelegationEntry defines a redelegation object with relevant metadata. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `creation_height` | [int64](#int64) | | | +| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `initial_balance` | [string](#string) | | | +| `shares_dst` | [string](#string) | | | - -

      Top

      -## cosmos/upgrade/v1beta1/query.proto - + -### QueryAppliedPlanRequest -QueryCurrentPlanRequest is the request type for the Query/AppliedPlan RPC -method. +### RedelegationEntryResponse +RedelegationEntryResponse is equivalent to a RedelegationEntry except that it +contains a balance in addition to shares which is more suitable for client +responses. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | name is the name of the applied plan to query for. | +| `redelegation_entry` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | | | +| `balance` | [string](#string) | | | - + -### QueryAppliedPlanResponse -QueryAppliedPlanResponse is the response type for the Query/AppliedPlan RPC -method. +### RedelegationResponse +RedelegationResponse is equivalent to a Redelegation except that its entries +contain a balance in addition to shares which is more suitable for client +responses. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | height is the block height at which the plan was applied. | +| `redelegation` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | | | +| `entries` | [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) | repeated | | - + -### QueryCurrentPlanRequest -QueryCurrentPlanRequest is the request type for the Query/CurrentPlan RPC -method. +### UnbondingDelegation +UnbondingDelegation stores all of a single delegator's unbonding bonds +for a single validator in an time-ordered list. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | +| `entries` | [UnbondingDelegationEntry](#cosmos.staking.v1beta1.UnbondingDelegationEntry) | repeated | unbonding delegation entries | + - -### QueryCurrentPlanResponse -QueryCurrentPlanResponse is the response type for the Query/CurrentPlan RPC -method. + + +### UnbondingDelegationEntry +UnbondingDelegationEntry defines an unbonding object with relevant metadata. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | plan is the current upgrade plan. | +| `creation_height` | [int64](#int64) | | | +| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `initial_balance` | [string](#string) | | | +| `balance` | [string](#string) | | | - + -### QueryUpgradedConsensusStateRequest -QueryUpgradedConsensusStateRequest is the request type for the Query/UpgradedConsensusState -RPC method. +### ValAddresses +ValAddresses defines a repeated set of validator addresses. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `last_height` | [int64](#int64) | | last height of the current chain must be sent in request as this is the height under which next consensus state is stored | +| `addresses` | [string](#string) | repeated | | - + -### QueryUpgradedConsensusStateResponse -QueryUpgradedConsensusStateResponse is the response type for the Query/UpgradedConsensusState -RPC method. +### Validator +Validator defines a validator, together with the total amount of the +Validator's bond shares and their exchange rate to coins. Slashing results in +a decrease in the exchange rate, allowing correct calculation of future +undelegations without iterating over delegators. When coins are delegated to +this validator, the validator is credited with a delegation whose number of +bond shares is based on the amount of coins delegated divided by the current +exchange rate. Voting power can be calculated as total bonded shares +multiplied by exchange rate. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `upgraded_consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `operator_address` | [string](#string) | | | +| `consensus_pubkey` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `jailed` | [bool](#bool) | | | +| `status` | [BondStatus](#cosmos.staking.v1beta1.BondStatus) | | | +| `tokens` | [string](#string) | | | +| `delegator_shares` | [string](#string) | | | +| `description` | [Description](#cosmos.staking.v1beta1.Description) | | | +| `unbonding_height` | [int64](#int64) | | | +| `unbonding_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `commission` | [Commission](#cosmos.staking.v1beta1.Commission) | | | +| `min_self_delegation` | [string](#string) | | | @@ -7135,21 +7357,23 @@ RPC method. - - - + - +### BondStatus +BondStatus is the status of a validator. -### Query -Query defines the gRPC upgrade querier service. +| Name | Number | Description | +| ---- | ------ | ----------- | +| BOND_STATUS_UNSPECIFIED | 0 | UNSPECIFIED defines an invalid validator status. | +| BOND_STATUS_UNBONDED | 1 | UNBONDED defines a validator that is not bonded. | +| BOND_STATUS_UNBONDING | 2 | UNBONDING defines a validator that is unbonding. | +| BOND_STATUS_BONDED | 3 | BONDED defines a validator that is bonded. | -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `CurrentPlan` | [QueryCurrentPlanRequest](#cosmos.upgrade.v1beta1.QueryCurrentPlanRequest) | [QueryCurrentPlanResponse](#cosmos.upgrade.v1beta1.QueryCurrentPlanResponse) | CurrentPlan queries the current upgrade plan. | GET|/cosmos/upgrade/v1beta1/current_plan| -| `AppliedPlan` | [QueryAppliedPlanRequest](#cosmos.upgrade.v1beta1.QueryAppliedPlanRequest) | [QueryAppliedPlanResponse](#cosmos.upgrade.v1beta1.QueryAppliedPlanResponse) | AppliedPlan queries a previously applied upgrade plan by its name. | GET|/cosmos/upgrade/v1beta1/applied_plan/{name}| -| `UpgradedConsensusState` | [QueryUpgradedConsensusStateRequest](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateRequest) | [QueryUpgradedConsensusStateResponse](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse) | UpgradedConsensusState queries the consensus state that will serve as a trusted kernel for the next version of this chain. It will only be stored at the last height of this chain. UpgradedConsensusState RPC not supported with legacy querier | GET|/cosmos/upgrade/v1beta1/upgraded_consensus_state/{last_height}| + + + + @@ -7315,96 +7539,99 @@ periodically vests by unlocking coins during each specified period. - +

      Top

      -## ibc/applications/transfer/v1/transfer.proto +## cosmos/params/v1beta1/query.proto - + -### DenomTrace -DenomTrace contains the base denomination for ICS20 fungible tokens and the -source tracing information path. +### QueryParamsRequest +QueryParamsRequest is request type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [string](#string) | | path defines the chain of port/channel identifiers used for tracing the source of the fungible token. | -| `base_denom` | [string](#string) | | base denomination of the relayed fungible token. | +| `subspace` | [string](#string) | | subspace defines the module to query the parameter for. | +| `key` | [string](#string) | | key defines the key of the parameter in the subspace. | - + -### FungibleTokenPacketData -FungibleTokenPacketData defines a struct for the packet payload -See FungibleTokenPacketData spec: -https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures +### QueryParamsResponse +QueryParamsResponse is response type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | the token denomination to be transferred | -| `amount` | [uint64](#uint64) | | the token amount to be transferred | -| `sender` | [string](#string) | | the sender address | -| `receiver` | [string](#string) | | the recipient address on the destination chain | +| `param` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | | param defines the queried parameter. | + - + -### Params -Params defines the set of IBC transfer parameters. -NOTE: To prevent a single token from being transferred, set the -TransfersEnabled parameter to true and then set the bank module's SendEnabled -parameter for the denomination to false. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `send_enabled` | [bool](#bool) | | send_enabled enables or disables all cross-chain token transfers from this chain. | -| `receive_enabled` | [bool](#bool) | | receive_enabled enables or disables all cross-chain token transfers to this chain. | + +### Query +Query defines the gRPC querier service. +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Params` | [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) | Params queries a specific parameter of a module, given its subspace and key. | GET|/cosmos/params/v1beta1/params| + - - + +

      Top

      - +## cosmos/params/v1beta1/params.proto - + - -

      Top

      +### ParamChange +ParamChange defines an individual parameter change, for use in +ParameterChangeProposal. -## ibc/applications/transfer/v1/genesis.proto +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `subspace` | [string](#string) | | | +| `key` | [string](#string) | | | +| `value` | [string](#string) | | | - -### GenesisState -GenesisState defines the ibc-transfer genesis state + + + + + +### ParameterChangeProposal +ParameterChangeProposal defines a proposal to change one or more parameters. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `denom_traces` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | repeated | | -| `params` | [Params](#ibc.applications.transfer.v1.Params) | | | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `changes` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | repeated | | @@ -7523,16 +7750,180 @@ QueryParamsResponse is the response type for the Query/Params RPC method. - + + +### Query +Query provides defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `DenomTrace` | [QueryDenomTraceRequest](#ibc.applications.transfer.v1.QueryDenomTraceRequest) | [QueryDenomTraceResponse](#ibc.applications.transfer.v1.QueryDenomTraceResponse) | DenomTrace queries a denomination trace information. | GET|/ibc/applications/transfer/v1beta1/denom_traces/{hash}| +| `DenomTraces` | [QueryDenomTracesRequest](#ibc.applications.transfer.v1.QueryDenomTracesRequest) | [QueryDenomTracesResponse](#ibc.applications.transfer.v1.QueryDenomTracesResponse) | DenomTraces queries all denomination traces. | GET|/ibc/applications/transfer/v1beta1/denom_traces| +| `Params` | [QueryParamsRequest](#ibc.applications.transfer.v1.QueryParamsRequest) | [QueryParamsResponse](#ibc.applications.transfer.v1.QueryParamsResponse) | Params queries all parameters of the ibc-transfer module. | GET|/ibc/applications/transfer/v1beta1/params| + + + + + + +

      Top

      + +## ibc/applications/transfer/v1/tx.proto + + + + + +### MsgTransfer +MsgTransfer defines a msg to transfer fungible tokens (i.e Coins) between +ICS20 enabled chains. See ICS Spec here: +https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `source_port` | [string](#string) | | the port on which the packet will be sent | +| `source_channel` | [string](#string) | | the channel by which the packet will be sent | +| `token` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | the tokens to be transferred | +| `sender` | [string](#string) | | the sender address | +| `receiver` | [string](#string) | | the recipient address on the destination chain | +| `timeout_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Timeout height relative to the current block height. The timeout is disabled when set to 0. | +| `timeout_timestamp` | [uint64](#uint64) | | Timeout timestamp (in nanoseconds) relative to the current block timestamp. The timeout is disabled when set to 0. | + + + + + + + + +### MsgTransferResponse +MsgTransferResponse defines the Msg/Transfer response type. + + + + + + + + + + + + + + +### Msg +Msg defines the ibc/transfer Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Transfer` | [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) | [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) | Transfer defines a rpc handler method for MsgTransfer. | | + + + + + + +

      Top

      + +## ibc/applications/transfer/v1/transfer.proto + + + + + +### DenomTrace +DenomTrace contains the base denomination for ICS20 fungible tokens and the +source tracing information path. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `path` | [string](#string) | | path defines the chain of port/channel identifiers used for tracing the source of the fungible token. | +| `base_denom` | [string](#string) | | base denomination of the relayed fungible token. | + + + + + + + + +### FungibleTokenPacketData +FungibleTokenPacketData defines a struct for the packet payload +See FungibleTokenPacketData spec: +https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `denom` | [string](#string) | | the token denomination to be transferred | +| `amount` | [uint64](#uint64) | | the token amount to be transferred | +| `sender` | [string](#string) | | the sender address | +| `receiver` | [string](#string) | | the recipient address on the destination chain | + + + + + + + + +### Params +Params defines the set of IBC transfer parameters. +NOTE: To prevent a single token from being transferred, set the +TransfersEnabled parameter to true and then set the bank module's SendEnabled +parameter for the denomination to false. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `send_enabled` | [bool](#bool) | | send_enabled enables or disables all cross-chain token transfers from this chain. | +| `receive_enabled` | [bool](#bool) | | receive_enabled enables or disables all cross-chain token transfers to this chain. | + + + + + + + + + + + + + + + + +

      Top

      + +## ibc/applications/transfer/v1/genesis.proto + + + + + +### GenesisState +GenesisState defines the ibc-transfer genesis state + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `port_id` | [string](#string) | | | +| `denom_traces` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | repeated | | +| `params` | [Params](#ibc.applications.transfer.v1.Params) | | | + + + + + + -### Query -Query provides defines the gRPC querier service. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `DenomTrace` | [QueryDenomTraceRequest](#ibc.applications.transfer.v1.QueryDenomTraceRequest) | [QueryDenomTraceResponse](#ibc.applications.transfer.v1.QueryDenomTraceResponse) | DenomTrace queries a denomination trace information. | GET|/ibc/applications/transfer/v1beta1/denom_traces/{hash}| -| `DenomTraces` | [QueryDenomTracesRequest](#ibc.applications.transfer.v1.QueryDenomTracesRequest) | [QueryDenomTracesResponse](#ibc.applications.transfer.v1.QueryDenomTracesResponse) | DenomTraces queries all denomination traces. | GET|/ibc/applications/transfer/v1beta1/denom_traces| -| `Params` | [QueryParamsRequest](#ibc.applications.transfer.v1.QueryParamsRequest) | [QueryParamsResponse](#ibc.applications.transfer.v1.QueryParamsResponse) | Params queries all parameters of the ibc-transfer module. | GET|/ibc/applications/transfer/v1beta1/params| + @@ -7663,682 +8054,615 @@ Params defines the set of IBC light client parameters. - +

      Top

      -## ibc/applications/transfer/v1/tx.proto - - - - - -### MsgTransfer -MsgTransfer defines a msg to transfer fungible tokens (i.e Coins) between -ICS20 enabled chains. See ICS Spec here: -https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures +## ibc/core/client/v1/query.proto -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `source_port` | [string](#string) | | the port on which the packet will be sent | -| `source_channel` | [string](#string) | | the channel by which the packet will be sent | -| `token` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | the tokens to be transferred | -| `sender` | [string](#string) | | the sender address | -| `receiver` | [string](#string) | | the recipient address on the destination chain | -| `timeout_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Timeout height relative to the current block height. The timeout is disabled when set to 0. | -| `timeout_timestamp` | [uint64](#uint64) | | Timeout timestamp (in nanoseconds) relative to the current block timestamp. The timeout is disabled when set to 0. | + +### QueryClientParamsRequest +QueryClientParamsRequest is the request type for the Query/ClientParams RPC method. - -### MsgTransferResponse -MsgTransferResponse defines the Msg/Transfer response type. + +### QueryClientParamsResponse +QueryClientParamsResponse is the response type for the Query/ClientParams RPC method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params` | [Params](#ibc.core.client.v1.Params) | | params defines the parameters of the module. | - - - - -### Msg -Msg defines the ibc/transfer Msg service. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Transfer` | [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) | [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) | Transfer defines a rpc handler method for MsgTransfer. | | +### QueryClientStateRequest +QueryClientStateRequest is the request type for the Query/ClientState RPC +method - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client state unique identifier | - -

      Top

      -## ibc/core/channel/v1/channel.proto - + -### Acknowledgement -Acknowledgement is the recommended acknowledgement format to be used by -app-specific protocols. -NOTE: The field numbers 21 and 22 were explicitly chosen to avoid accidental -conflicts with other protobuf message formats used for acknowledgements. -The first byte of any message with this format will be the non-ASCII values -`0xaa` (result) or `0xb2` (error). Implemented as defined by ICS: -https://github.com/cosmos/ics/tree/master/spec/ics-004-channel-and-packet-semantics#acknowledgement-envelope +### QueryClientStateResponse +QueryClientStateResponse is the response type for the Query/ClientState RPC +method. Besides the client state, it includes a proof and the height from +which the proof was retrieved. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `result` | [bytes](#bytes) | | | -| `error` | [string](#string) | | | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | client state associated with the request identifier | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - + -### Channel -Channel defines pipeline for exactly-once packet delivery between specific -modules on separate blockchains, which has at least one end capable of -sending packets and one end capable of receiving packets. +### QueryClientStatesRequest +QueryClientStatesRequest is the request type for the Query/ClientStates RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `state` | [State](#ibc.core.channel.v1.State) | | current state of the channel end | -| `ordering` | [Order](#ibc.core.channel.v1.Order) | | whether the channel is ordered or unordered | -| `counterparty` | [Counterparty](#ibc.core.channel.v1.Counterparty) | | counterparty channel end | -| `connection_hops` | [string](#string) | repeated | list of connection identifiers, in order, along which packets sent on this channel will travel | -| `version` | [string](#string) | | opaque channel version, which is agreed upon during the handshake | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - + -### Counterparty -Counterparty defines a channel end counterparty +### QueryClientStatesResponse +QueryClientStatesResponse is the response type for the Query/ClientStates RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port on the counterparty chain which owns the other end of the channel. | -| `channel_id` | [string](#string) | | channel end on the counterparty chain | +| `client_states` | [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | repeated | list of stored ClientStates of the chain. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | - + -### IdentifiedChannel -IdentifiedChannel defines a channel with additional port and channel -identifier fields. +### QueryConsensusStateRequest +QueryConsensusStateRequest is the request type for the Query/ConsensusState +RPC method. Besides the consensus state, it includes a proof and the height +from which the proof was retrieved. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `state` | [State](#ibc.core.channel.v1.State) | | current state of the channel end | -| `ordering` | [Order](#ibc.core.channel.v1.Order) | | whether the channel is ordered or unordered | -| `counterparty` | [Counterparty](#ibc.core.channel.v1.Counterparty) | | counterparty channel end | -| `connection_hops` | [string](#string) | repeated | list of connection identifiers, in order, along which packets sent on this channel will travel | -| `version` | [string](#string) | | opaque channel version, which is agreed upon during the handshake | -| `port_id` | [string](#string) | | port identifier | -| `channel_id` | [string](#string) | | channel identifier | +| `client_id` | [string](#string) | | client identifier | +| `revision_number` | [uint64](#uint64) | | consensus state revision number | +| `revision_height` | [uint64](#uint64) | | consensus state revision height | +| `latest_height` | [bool](#bool) | | latest_height overrrides the height field and queries the latest stored ConsensusState | - + -### Packet -Packet defines a type that carries data across different chains through IBC +### QueryConsensusStateResponse +QueryConsensusStateResponse is the response type for the Query/ConsensusState +RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `sequence` | [uint64](#uint64) | | number corresponds to the order of sends and receives, where a Packet with an earlier sequence number must be sent and received before a Packet with a later sequence number. | -| `source_port` | [string](#string) | | identifies the port on the sending chain. | -| `source_channel` | [string](#string) | | identifies the channel end on the sending chain. | -| `destination_port` | [string](#string) | | identifies the port on the receiving chain. | -| `destination_channel` | [string](#string) | | identifies the channel end on the receiving chain. | -| `data` | [bytes](#bytes) | | actual opaque bytes transferred directly to the application module | -| `timeout_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | block height after which the packet times out | -| `timeout_timestamp` | [uint64](#uint64) | | block timestamp (in nanoseconds) after which the packet times out | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the client identifier at the given height | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - + -### PacketState -PacketState defines the generic type necessary to retrieve and store -packet commitments, acknowledgements, and receipts. -Caller is responsible for knowing the context necessary to interpret this -state as a commitment, acknowledgement, or a receipt. +### QueryConsensusStatesRequest +QueryConsensusStatesRequest is the request type for the Query/ConsensusStates +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | channel port identifier. | -| `channel_id` | [string](#string) | | channel unique identifier. | -| `sequence` | [uint64](#uint64) | | packet sequence. | -| `data` | [bytes](#bytes) | | embedded data that represents packet state. | - +| `client_id` | [string](#string) | | client identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - - + -### Order -Order defines if a channel is ORDERED or UNORDERED +### QueryConsensusStatesResponse +QueryConsensusStatesResponse is the response type for the +Query/ConsensusStates RPC method -| Name | Number | Description | -| ---- | ------ | ----------- | -| ORDER_NONE_UNSPECIFIED | 0 | zero-value for channel ordering | -| ORDER_UNORDERED | 1 | packets can be delivered in any order, which may differ from the order in which they were sent. | -| ORDER_ORDERED | 2 | packets are delivered exactly in the order which they were sent | +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `consensus_states` | [ConsensusStateWithHeight](#ibc.core.client.v1.ConsensusStateWithHeight) | repeated | consensus states associated with the identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | - -### State -State defines if a channel is in one of the following states: -CLOSED, INIT, TRYOPEN, OPEN or UNINITIALIZED. -| Name | Number | Description | -| ---- | ------ | ----------- | -| STATE_UNINITIALIZED_UNSPECIFIED | 0 | Default State | -| STATE_INIT | 1 | A channel has just started the opening handshake. | -| STATE_TRYOPEN | 2 | A channel has acknowledged the handshake step on the counterparty chain. | -| STATE_OPEN | 3 | A channel has completed the handshake. Open channels are ready to send and receive packets. | -| STATE_CLOSED | 4 | A channel has been closed and can no longer be used to send or receive packets. | + - - - - - -

      Top

      - -## ibc/core/channel/v1/genesis.proto - - - - - -### GenesisState -GenesisState defines the ibc channel submodule's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `channels` | [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) | repeated | | -| `acknowledgements` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | -| `commitments` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | -| `receipts` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | -| `send_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | -| `recv_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | -| `ack_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | -| `next_channel_sequence` | [uint64](#uint64) | | the sequence for the next generated channel identifier | - - - + +### Query +Query provides defines the gRPC querier service - - -### PacketSequence -PacketSequence defines the genesis type necessary to retrieve and store -next send and receive sequences. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel_id` | [string](#string) | | | -| `sequence` | [uint64](#uint64) | | | +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `ClientState` | [QueryClientStateRequest](#ibc.core.client.v1.QueryClientStateRequest) | [QueryClientStateResponse](#ibc.core.client.v1.QueryClientStateResponse) | ClientState queries an IBC light client. | GET|/ibc/core/client/v1beta1/client_states/{client_id}| +| `ClientStates` | [QueryClientStatesRequest](#ibc.core.client.v1.QueryClientStatesRequest) | [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse) | ClientStates queries all the IBC light clients of a chain. | GET|/ibc/core/client/v1beta1/client_states| +| `ConsensusState` | [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest) | [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) | ConsensusState queries a consensus state associated with a client state at a given height. | GET|/ibc/core/client/v1beta1/consensus_states/{client_id}/revision/{revision_number}/height/{revision_height}| +| `ConsensusStates` | [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) | [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) | ConsensusStates queries all the consensus state associated with a given client. | GET|/ibc/core/client/v1beta1/consensus_states/{client_id}| +| `ClientParams` | [QueryClientParamsRequest](#ibc.core.client.v1.QueryClientParamsRequest) | [QueryClientParamsResponse](#ibc.core.client.v1.QueryClientParamsResponse) | ClientParams queries all parameters of the ibc client. | GET|/ibc/client/v1beta1/params| + + +

      Top

      - +## ibc/core/client/v1/tx.proto - - - + +### MsgCreateClient +MsgCreateClient defines a message to create an IBC client - -

      Top

      +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | light client state | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the client that corresponds to a given height. | +| `signer` | [string](#string) | | signer address | -## ibc/core/channel/v1/query.proto - -### QueryChannelClientStateRequest -QueryChannelClientStateRequest is the request type for the Query/ClientState -RPC method + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | +### MsgCreateClientResponse +MsgCreateClientResponse defines the Msg/CreateClient response type. - + -### QueryChannelClientStateResponse -QueryChannelClientStateResponse is the Response type for the -Query/QueryChannelClientState RPC method +### MsgSubmitMisbehaviour +MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for +light client misbehaviour. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `identified_client_state` | [ibc.core.client.v1.IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | | client state associated with the channel | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - - +| `client_id` | [string](#string) | | client unique identifier | +| `misbehaviour` | [google.protobuf.Any](#google.protobuf.Any) | | misbehaviour used for freezing the light client | +| `signer` | [string](#string) | | signer address | - -### QueryChannelConsensusStateRequest -QueryChannelConsensusStateRequest is the request type for the -Query/ConsensusState RPC method + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | -| `revision_number` | [uint64](#uint64) | | revision number of the consensus state | -| `revision_height` | [uint64](#uint64) | | revision height of the consensus state | +### MsgSubmitMisbehaviourResponse +MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response type. - + -### QueryChannelConsensusStateResponse -QueryChannelClientStateResponse is the Response type for the -Query/QueryChannelClientState RPC method +### MsgUpdateClient +MsgUpdateClient defines an sdk.Msg to update a IBC client state using +the given header. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the channel | -| `client_id` | [string](#string) | | client ID associated with the consensus state | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - - +| `client_id` | [string](#string) | | client unique identifier | +| `header` | [google.protobuf.Any](#google.protobuf.Any) | | header to update the light client | +| `signer` | [string](#string) | | signer address | - -### QueryChannelRequest -QueryChannelRequest is the request type for the Query/Channel RPC method + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | +### MsgUpdateClientResponse +MsgUpdateClientResponse defines the Msg/UpdateClient response type. - + -### QueryChannelResponse -QueryChannelResponse is the response type for the Query/Channel RPC method. -Besides the Channel end, it includes a proof and the height from which the -proof was retrieved. +### MsgUpgradeClient +MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `channel` | [Channel](#ibc.core.channel.v1.Channel) | | channel associated with the request identifiers | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | +| `client_id` | [string](#string) | | client unique identifier | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | upgraded client state | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | upgraded consensus state, only contains enough information to serve as a basis of trust in update logic | +| `proof_upgrade_client` | [bytes](#bytes) | | proof that old chain committed to new client | +| `proof_upgrade_consensus_state` | [bytes](#bytes) | | proof that old chain committed to new consensus state | +| `signer` | [string](#string) | | signer address | - + -### QueryChannelsRequest -QueryChannelsRequest is the request type for the Query/Channels RPC method +### MsgUpgradeClientResponse +MsgUpgradeClientResponse defines the Msg/UpgradeClient response type. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | + + + - -### QueryChannelsResponse -QueryChannelsResponse is the response type for the Query/Channels RPC method. + +### Msg +Msg defines the ibc/client Msg service. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `channels` | [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) | repeated | list of stored channels of the chain. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | -| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `CreateClient` | [MsgCreateClient](#ibc.core.client.v1.MsgCreateClient) | [MsgCreateClientResponse](#ibc.core.client.v1.MsgCreateClientResponse) | CreateClient defines a rpc handler method for MsgCreateClient. | | +| `UpdateClient` | [MsgUpdateClient](#ibc.core.client.v1.MsgUpdateClient) | [MsgUpdateClientResponse](#ibc.core.client.v1.MsgUpdateClientResponse) | UpdateClient defines a rpc handler method for MsgUpdateClient. | | +| `UpgradeClient` | [MsgUpgradeClient](#ibc.core.client.v1.MsgUpgradeClient) | [MsgUpgradeClientResponse](#ibc.core.client.v1.MsgUpgradeClientResponse) | UpgradeClient defines a rpc handler method for MsgUpgradeClient. | | +| `SubmitMisbehaviour` | [MsgSubmitMisbehaviour](#ibc.core.client.v1.MsgSubmitMisbehaviour) | [MsgSubmitMisbehaviourResponse](#ibc.core.client.v1.MsgSubmitMisbehaviourResponse) | SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour. | | + + +

      Top

      +## ibc/core/client/v1/genesis.proto - -### QueryConnectionChannelsRequest -QueryConnectionChannelsRequest is the request type for the -Query/QueryConnectionChannels RPC method + + + +### GenesisMetadata +GenesisMetadata defines the genesis type for metadata that clients may return +with ExportMetadata | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `connection` | [string](#string) | | connection unique identifier | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | +| `key` | [bytes](#bytes) | | store key of metadata without clientID-prefix | +| `value` | [bytes](#bytes) | | metadata value | - + -### QueryConnectionChannelsResponse -QueryConnectionChannelsResponse is the Response type for the -Query/QueryConnectionChannels RPC method +### GenesisState +GenesisState defines the ibc client submodule's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `channels` | [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) | repeated | list of channels associated with a connection. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | -| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | +| `clients` | [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | repeated | client states with their corresponding identifiers | +| `clients_consensus` | [ClientConsensusStates](#ibc.core.client.v1.ClientConsensusStates) | repeated | consensus states from each client | +| `clients_metadata` | [IdentifiedGenesisMetadata](#ibc.core.client.v1.IdentifiedGenesisMetadata) | repeated | metadata from each client | +| `params` | [Params](#ibc.core.client.v1.Params) | | | +| `create_localhost` | [bool](#bool) | | create localhost on initialization | +| `next_client_sequence` | [uint64](#uint64) | | the sequence for the next generated client identifier | - + -### QueryNextSequenceReceiveRequest -QueryNextSequenceReceiveRequest is the request type for the -Query/QueryNextSequenceReceiveRequest RPC method +### IdentifiedGenesisMetadata +IdentifiedGenesisMetadata has the client metadata with the corresponding client id. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | +| `client_id` | [string](#string) | | | +| `client_metadata` | [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) | repeated | | + - + -### QueryNextSequenceReceiveResponse -QuerySequenceResponse is the request type for the -Query/QueryNextSequenceReceiveResponse RPC method + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `next_sequence_receive` | [uint64](#uint64) | | next sequence receive number | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | + +

      Top

      +## ibc/core/channel/v1/channel.proto - + -### QueryPacketAcknowledgementRequest -QueryPacketAcknowledgementRequest is the request type for the -Query/PacketAcknowledgement RPC method +### Acknowledgement +Acknowledgement is the recommended acknowledgement format to be used by +app-specific protocols. +NOTE: The field numbers 21 and 22 were explicitly chosen to avoid accidental +conflicts with other protobuf message formats used for acknowledgements. +The first byte of any message with this format will be the non-ASCII values +`0xaa` (result) or `0xb2` (error). Implemented as defined by ICS: +https://github.com/cosmos/ics/tree/master/spec/ics-004-channel-and-packet-semantics#acknowledgement-envelope | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | -| `sequence` | [uint64](#uint64) | | packet sequence | +| `result` | [bytes](#bytes) | | | +| `error` | [string](#string) | | | - + -### QueryPacketAcknowledgementResponse -QueryPacketAcknowledgementResponse defines the client query response for a -packet which also includes a proof and the height from which the -proof was retrieved +### Channel +Channel defines pipeline for exactly-once packet delivery between specific +modules on separate blockchains, which has at least one end capable of +sending packets and one end capable of receiving packets. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `acknowledgement` | [bytes](#bytes) | | packet associated with the request fields | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | +| `state` | [State](#ibc.core.channel.v1.State) | | current state of the channel end | +| `ordering` | [Order](#ibc.core.channel.v1.Order) | | whether the channel is ordered or unordered | +| `counterparty` | [Counterparty](#ibc.core.channel.v1.Counterparty) | | counterparty channel end | +| `connection_hops` | [string](#string) | repeated | list of connection identifiers, in order, along which packets sent on this channel will travel | +| `version` | [string](#string) | | opaque channel version, which is agreed upon during the handshake | - + -### QueryPacketAcknowledgementsRequest -QueryPacketAcknowledgementsRequest is the request type for the -Query/QueryPacketCommitments RPC method +### Counterparty +Counterparty defines a channel end counterparty | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | +| `port_id` | [string](#string) | | port on the counterparty chain which owns the other end of the channel. | +| `channel_id` | [string](#string) | | channel end on the counterparty chain | - + -### QueryPacketAcknowledgementsResponse -QueryPacketAcknowledgemetsResponse is the request type for the -Query/QueryPacketAcknowledgements RPC method +### IdentifiedChannel +IdentifiedChannel defines a channel with additional port and channel +identifier fields. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `acknowledgements` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | -| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | +| `state` | [State](#ibc.core.channel.v1.State) | | current state of the channel end | +| `ordering` | [Order](#ibc.core.channel.v1.Order) | | whether the channel is ordered or unordered | +| `counterparty` | [Counterparty](#ibc.core.channel.v1.Counterparty) | | counterparty channel end | +| `connection_hops` | [string](#string) | repeated | list of connection identifiers, in order, along which packets sent on this channel will travel | +| `version` | [string](#string) | | opaque channel version, which is agreed upon during the handshake | +| `port_id` | [string](#string) | | port identifier | +| `channel_id` | [string](#string) | | channel identifier | - + -### QueryPacketCommitmentRequest -QueryPacketCommitmentRequest is the request type for the -Query/PacketCommitment RPC method +### Packet +Packet defines a type that carries data across different chains through IBC | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | -| `sequence` | [uint64](#uint64) | | packet sequence | +| `sequence` | [uint64](#uint64) | | number corresponds to the order of sends and receives, where a Packet with an earlier sequence number must be sent and received before a Packet with a later sequence number. | +| `source_port` | [string](#string) | | identifies the port on the sending chain. | +| `source_channel` | [string](#string) | | identifies the channel end on the sending chain. | +| `destination_port` | [string](#string) | | identifies the port on the receiving chain. | +| `destination_channel` | [string](#string) | | identifies the channel end on the receiving chain. | +| `data` | [bytes](#bytes) | | actual opaque bytes transferred directly to the application module | +| `timeout_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | block height after which the packet times out | +| `timeout_timestamp` | [uint64](#uint64) | | block timestamp (in nanoseconds) after which the packet times out | - + -### QueryPacketCommitmentResponse -QueryPacketCommitmentResponse defines the client query response for a packet -which also includes a proof and the height from which the proof was -retrieved +### PacketState +PacketState defines the generic type necessary to retrieve and store +packet commitments, acknowledgements, and receipts. +Caller is responsible for knowing the context necessary to interpret this +state as a commitment, acknowledgement, or a receipt. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `commitment` | [bytes](#bytes) | | packet associated with the request fields | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | +| `port_id` | [string](#string) | | channel port identifier. | +| `channel_id` | [string](#string) | | channel unique identifier. | +| `sequence` | [uint64](#uint64) | | packet sequence. | +| `data` | [bytes](#bytes) | | embedded data that represents packet state. | + - -### QueryPacketCommitmentsRequest -QueryPacketCommitmentsRequest is the request type for the -Query/QueryPacketCommitments RPC method + +### Order +Order defines if a channel is ORDERED or UNORDERED + +| Name | Number | Description | +| ---- | ------ | ----------- | +| ORDER_NONE_UNSPECIFIED | 0 | zero-value for channel ordering | +| ORDER_UNORDERED | 1 | packets can be delivered in any order, which may differ from the order in which they were sent. | +| ORDER_ORDERED | 2 | packets are delivered exactly in the order which they were sent | -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | + +### State +State defines if a channel is in one of the following states: +CLOSED, INIT, TRYOPEN, OPEN or UNINITIALIZED. +| Name | Number | Description | +| ---- | ------ | ----------- | +| STATE_UNINITIALIZED_UNSPECIFIED | 0 | Default State | +| STATE_INIT | 1 | A channel has just started the opening handshake. | +| STATE_TRYOPEN | 2 | A channel has acknowledged the handshake step on the counterparty chain. | +| STATE_OPEN | 3 | A channel has completed the handshake. Open channels are ready to send and receive packets. | +| STATE_CLOSED | 4 | A channel has been closed and can no longer be used to send or receive packets. | - + -### QueryPacketCommitmentsResponse -QueryPacketCommitmentsResponse is the request type for the -Query/QueryPacketCommitments RPC method + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `commitments` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | -| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | + +

      Top

      +## ibc/core/channel/v1/query.proto - + -### QueryPacketReceiptRequest -QueryPacketReceiptRequest is the request type for the -Query/PacketReceipt RPC method +### QueryChannelClientStateRequest +QueryChannelClientStateRequest is the request type for the Query/ClientState +RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `port_id` | [string](#string) | | port unique identifier | | `channel_id` | [string](#string) | | channel unique identifier | -| `sequence` | [uint64](#uint64) | | packet sequence | - + -### QueryPacketReceiptResponse -QueryPacketReceiptResponse defines the client query response for a packet receipt -which also includes a proof, and the height from which the proof was -retrieved +### QueryChannelClientStateResponse +QueryChannelClientStateResponse is the Response type for the +Query/QueryChannelClientState RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `received` | [bool](#bool) | | success flag for if receipt exists | +| `identified_client_state` | [ibc.core.client.v1.IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | | client state associated with the channel | | `proof` | [bytes](#bytes) | | merkle proof of existence | | `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | @@ -8347,404 +8671,428 @@ retrieved - + -### QueryUnreceivedAcksRequest -QueryUnreceivedAcks is the request type for the -Query/UnreceivedAcks RPC method +### QueryChannelConsensusStateRequest +QueryChannelConsensusStateRequest is the request type for the +Query/ConsensusState RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `port_id` | [string](#string) | | port unique identifier | | `channel_id` | [string](#string) | | channel unique identifier | -| `packet_ack_sequences` | [uint64](#uint64) | repeated | list of acknowledgement sequences | +| `revision_number` | [uint64](#uint64) | | revision number of the consensus state | +| `revision_height` | [uint64](#uint64) | | revision height of the consensus state | - + -### QueryUnreceivedAcksResponse -QueryUnreceivedAcksResponse is the response type for the -Query/UnreceivedAcks RPC method +### QueryChannelConsensusStateResponse +QueryChannelClientStateResponse is the Response type for the +Query/QueryChannelClientState RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `sequences` | [uint64](#uint64) | repeated | list of unreceived acknowledgement sequences | -| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the channel | +| `client_id` | [string](#string) | | client ID associated with the consensus state | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - + -### QueryUnreceivedPacketsRequest -QueryUnreceivedPacketsRequest is the request type for the -Query/UnreceivedPackets RPC method +### QueryChannelRequest +QueryChannelRequest is the request type for the Query/Channel RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `port_id` | [string](#string) | | port unique identifier | | `channel_id` | [string](#string) | | channel unique identifier | -| `packet_commitment_sequences` | [uint64](#uint64) | repeated | list of packet sequences | - + -### QueryUnreceivedPacketsResponse -QueryUnreceivedPacketsResponse is the response type for the -Query/UnreceivedPacketCommitments RPC method +### QueryChannelResponse +QueryChannelResponse is the response type for the Query/Channel RPC method. +Besides the Channel end, it includes a proof and the height from which the +proof was retrieved. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `sequences` | [uint64](#uint64) | repeated | list of unreceived packet sequences | -| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | - - - - +| `channel` | [Channel](#ibc.core.channel.v1.Channel) | | channel associated with the request identifiers | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - - - - -### Query -Query provides defines the gRPC querier service + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Channel` | [QueryChannelRequest](#ibc.core.channel.v1.QueryChannelRequest) | [QueryChannelResponse](#ibc.core.channel.v1.QueryChannelResponse) | Channel queries an IBC Channel. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}| -| `Channels` | [QueryChannelsRequest](#ibc.core.channel.v1.QueryChannelsRequest) | [QueryChannelsResponse](#ibc.core.channel.v1.QueryChannelsResponse) | Channels queries all the IBC channels of a chain. | GET|/ibc/core/channel/v1beta1/channels| -| `ConnectionChannels` | [QueryConnectionChannelsRequest](#ibc.core.channel.v1.QueryConnectionChannelsRequest) | [QueryConnectionChannelsResponse](#ibc.core.channel.v1.QueryConnectionChannelsResponse) | ConnectionChannels queries all the channels associated with a connection end. | GET|/ibc/core/channel/v1beta1/connections/{connection}/channels| -| `ChannelClientState` | [QueryChannelClientStateRequest](#ibc.core.channel.v1.QueryChannelClientStateRequest) | [QueryChannelClientStateResponse](#ibc.core.channel.v1.QueryChannelClientStateResponse) | ChannelClientState queries for the client state for the channel associated with the provided channel identifiers. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/client_state| -| `ChannelConsensusState` | [QueryChannelConsensusStateRequest](#ibc.core.channel.v1.QueryChannelConsensusStateRequest) | [QueryChannelConsensusStateResponse](#ibc.core.channel.v1.QueryChannelConsensusStateResponse) | ChannelConsensusState queries for the consensus state for the channel associated with the provided channel identifiers. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/consensus_state/revision/{revision_number}/height/{revision_height}| -| `PacketCommitment` | [QueryPacketCommitmentRequest](#ibc.core.channel.v1.QueryPacketCommitmentRequest) | [QueryPacketCommitmentResponse](#ibc.core.channel.v1.QueryPacketCommitmentResponse) | PacketCommitment queries a stored packet commitment hash. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/{sequence}| -| `PacketCommitments` | [QueryPacketCommitmentsRequest](#ibc.core.channel.v1.QueryPacketCommitmentsRequest) | [QueryPacketCommitmentsResponse](#ibc.core.channel.v1.QueryPacketCommitmentsResponse) | PacketCommitments returns all the packet commitments hashes associated with a channel. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments| -| `PacketReceipt` | [QueryPacketReceiptRequest](#ibc.core.channel.v1.QueryPacketReceiptRequest) | [QueryPacketReceiptResponse](#ibc.core.channel.v1.QueryPacketReceiptResponse) | PacketReceipt queries if a given packet sequence has been received on the queried chain | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_receipts/{sequence}| -| `PacketAcknowledgement` | [QueryPacketAcknowledgementRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementRequest) | [QueryPacketAcknowledgementResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementResponse) | PacketAcknowledgement queries a stored packet acknowledgement hash. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_acks/{sequence}| -| `PacketAcknowledgements` | [QueryPacketAcknowledgementsRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementsRequest) | [QueryPacketAcknowledgementsResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementsResponse) | PacketAcknowledgements returns all the packet acknowledgements associated with a channel. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_acknowledgements| -| `UnreceivedPackets` | [QueryUnreceivedPacketsRequest](#ibc.core.channel.v1.QueryUnreceivedPacketsRequest) | [QueryUnreceivedPacketsResponse](#ibc.core.channel.v1.QueryUnreceivedPacketsResponse) | UnreceivedPackets returns all the unreceived IBC packets associated with a channel and sequences. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/{packet_commitment_sequences}/unreceived_packets| -| `UnreceivedAcks` | [QueryUnreceivedAcksRequest](#ibc.core.channel.v1.QueryUnreceivedAcksRequest) | [QueryUnreceivedAcksResponse](#ibc.core.channel.v1.QueryUnreceivedAcksResponse) | UnreceivedAcks returns all the unreceived IBC acknowledgements associated with a channel and sequences. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/{packet_ack_sequences}/unreceived_acks| -| `NextSequenceReceive` | [QueryNextSequenceReceiveRequest](#ibc.core.channel.v1.QueryNextSequenceReceiveRequest) | [QueryNextSequenceReceiveResponse](#ibc.core.channel.v1.QueryNextSequenceReceiveResponse) | NextSequenceReceive returns the next receive sequence for a given channel. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/next_sequence| +### QueryChannelsRequest +QueryChannelsRequest is the request type for the Query/Channels RPC method - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - -

      Top

      -## ibc/core/channel/v1/tx.proto - + -### MsgAcknowledgement -MsgAcknowledgement receives incoming IBC acknowledgement +### QueryChannelsResponse +QueryChannelsResponse is the response type for the Query/Channels RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `packet` | [Packet](#ibc.core.channel.v1.Packet) | | | -| `acknowledgement` | [bytes](#bytes) | | | -| `proof_acked` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | - - - - - - - - -### MsgAcknowledgementResponse -MsgAcknowledgementResponse defines the Msg/Acknowledgement response type. +| `channels` | [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) | repeated | list of stored channels of the chain. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | - + -### MsgChannelCloseConfirm -MsgChannelCloseConfirm defines a msg sent by a Relayer to Chain B -to acknowledge the change of channel state to CLOSED on Chain A. +### QueryConnectionChannelsRequest +QueryConnectionChannelsRequest is the request type for the +Query/QueryConnectionChannels RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel_id` | [string](#string) | | | -| `proof_init` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | +| `connection` | [string](#string) | | connection unique identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - + -### MsgChannelCloseConfirmResponse -MsgChannelCloseConfirmResponse defines the Msg/ChannelCloseConfirm response type. +### QueryConnectionChannelsResponse +QueryConnectionChannelsResponse is the Response type for the +Query/QueryConnectionChannels RPC method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `channels` | [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) | repeated | list of channels associated with a connection. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | - + -### MsgChannelCloseInit -MsgChannelCloseInit defines a msg sent by a Relayer to Chain A -to close a channel with Chain B. +### QueryNextSequenceReceiveRequest +QueryNextSequenceReceiveRequest is the request type for the +Query/QueryNextSequenceReceiveRequest RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel_id` | [string](#string) | | | -| `signer` | [string](#string) | | | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | - + -### MsgChannelCloseInitResponse -MsgChannelCloseInitResponse defines the Msg/ChannelCloseInit response type. +### QueryNextSequenceReceiveResponse +QuerySequenceResponse is the request type for the +Query/QueryNextSequenceReceiveResponse RPC method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `next_sequence_receive` | [uint64](#uint64) | | next sequence receive number | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - + -### MsgChannelOpenAck -MsgChannelOpenAck defines a msg sent by a Relayer to Chain A to acknowledge -the change of channel state to TRYOPEN on Chain B. +### QueryPacketAcknowledgementRequest +QueryPacketAcknowledgementRequest is the request type for the +Query/PacketAcknowledgement RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel_id` | [string](#string) | | | -| `counterparty_channel_id` | [string](#string) | | | -| `counterparty_version` | [string](#string) | | | -| `proof_try` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `sequence` | [uint64](#uint64) | | packet sequence | - + -### MsgChannelOpenAckResponse -MsgChannelOpenAckResponse defines the Msg/ChannelOpenAck response type. +### QueryPacketAcknowledgementResponse +QueryPacketAcknowledgementResponse defines the client query response for a +packet which also includes a proof and the height from which the +proof was retrieved +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `acknowledgement` | [bytes](#bytes) | | packet associated with the request fields | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - -### MsgChannelOpenConfirm -MsgChannelOpenConfirm defines a msg sent by a Relayer to Chain B to -acknowledge the change of channel state to OPEN on Chain A. + + + +### QueryPacketAcknowledgementsRequest +QueryPacketAcknowledgementsRequest is the request type for the +Query/QueryPacketCommitments RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel_id` | [string](#string) | | | -| `proof_ack` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - + -### MsgChannelOpenConfirmResponse -MsgChannelOpenConfirmResponse defines the Msg/ChannelOpenConfirm response type. +### QueryPacketAcknowledgementsResponse +QueryPacketAcknowledgemetsResponse is the request type for the +Query/QueryPacketAcknowledgements RPC method +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `acknowledgements` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | - -### MsgChannelOpenInit -MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It -is called by a relayer on Chain A. + + + +### QueryPacketCommitmentRequest +QueryPacketCommitmentRequest is the request type for the +Query/PacketCommitment RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel` | [Channel](#ibc.core.channel.v1.Channel) | | | -| `signer` | [string](#string) | | | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `sequence` | [uint64](#uint64) | | packet sequence | - + + +### QueryPacketCommitmentResponse +QueryPacketCommitmentResponse defines the client query response for a packet +which also includes a proof and the height from which the proof was +retrieved -### MsgChannelOpenInitResponse -MsgChannelOpenInitResponse defines the Msg/ChannelOpenInit response type. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `commitment` | [bytes](#bytes) | | packet associated with the request fields | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - -### MsgChannelOpenTry -MsgChannelOpenInit defines a msg sent by a Relayer to try to open a channel -on Chain B. + + +### QueryPacketCommitmentsRequest +QueryPacketCommitmentsRequest is the request type for the +Query/QueryPacketCommitments RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `previous_channel_id` | [string](#string) | | in the case of crossing hello's, when both chains call OpenInit, we need the channel identifier of the previous channel in state INIT | -| `channel` | [Channel](#ibc.core.channel.v1.Channel) | | | -| `counterparty_version` | [string](#string) | | | -| `proof_init` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - + -### MsgChannelOpenTryResponse -MsgChannelOpenTryResponse defines the Msg/ChannelOpenTry response type. +### QueryPacketCommitmentsResponse +QueryPacketCommitmentsResponse is the request type for the +Query/QueryPacketCommitments RPC method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `commitments` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | - + -### MsgRecvPacket -MsgRecvPacket receives incoming IBC packet +### QueryPacketReceiptRequest +QueryPacketReceiptRequest is the request type for the +Query/PacketReceipt RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `packet` | [Packet](#ibc.core.channel.v1.Packet) | | | -| `proof_commitment` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `sequence` | [uint64](#uint64) | | packet sequence | - + -### MsgRecvPacketResponse -MsgRecvPacketResponse defines the Msg/RecvPacket response type. +### QueryPacketReceiptResponse +QueryPacketReceiptResponse defines the client query response for a packet receipt +which also includes a proof, and the height from which the proof was +retrieved +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `received` | [bool](#bool) | | success flag for if receipt exists | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - -### MsgTimeout -MsgTimeout receives timed-out packet + + + +### QueryUnreceivedAcksRequest +QueryUnreceivedAcks is the request type for the +Query/UnreceivedAcks RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `packet` | [Packet](#ibc.core.channel.v1.Packet) | | | -| `proof_unreceived` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `next_sequence_recv` | [uint64](#uint64) | | | -| `signer` | [string](#string) | | | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `packet_ack_sequences` | [uint64](#uint64) | repeated | list of acknowledgement sequences | - + -### MsgTimeoutOnClose -MsgTimeoutOnClose timed-out packet upon counterparty channel closure. +### QueryUnreceivedAcksResponse +QueryUnreceivedAcksResponse is the response type for the +Query/UnreceivedAcks RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `packet` | [Packet](#ibc.core.channel.v1.Packet) | | | -| `proof_unreceived` | [bytes](#bytes) | | | -| `proof_close` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `next_sequence_recv` | [uint64](#uint64) | | | -| `signer` | [string](#string) | | | +| `sequences` | [uint64](#uint64) | repeated | list of unreceived acknowledgement sequences | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | - + -### MsgTimeoutOnCloseResponse -MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type. +### QueryUnreceivedPacketsRequest +QueryUnreceivedPacketsRequest is the request type for the +Query/UnreceivedPackets RPC method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `packet_commitment_sequences` | [uint64](#uint64) | repeated | list of packet sequences | - + -### MsgTimeoutResponse -MsgTimeoutResponse defines the Msg/Timeout response type. +### QueryUnreceivedPacketsResponse +QueryUnreceivedPacketsResponse is the response type for the +Query/UnreceivedPacketCommitments RPC method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `sequences` | [uint64](#uint64) | repeated | list of unreceived packet sequences | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | @@ -8757,406 +9105,403 @@ MsgTimeoutResponse defines the Msg/Timeout response type. - + -### Msg -Msg defines the ibc/channel Msg service. +### Query +Query provides defines the gRPC querier service | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `ChannelOpenInit` | [MsgChannelOpenInit](#ibc.core.channel.v1.MsgChannelOpenInit) | [MsgChannelOpenInitResponse](#ibc.core.channel.v1.MsgChannelOpenInitResponse) | ChannelOpenInit defines a rpc handler method for MsgChannelOpenInit. | | -| `ChannelOpenTry` | [MsgChannelOpenTry](#ibc.core.channel.v1.MsgChannelOpenTry) | [MsgChannelOpenTryResponse](#ibc.core.channel.v1.MsgChannelOpenTryResponse) | ChannelOpenTry defines a rpc handler method for MsgChannelOpenTry. | | -| `ChannelOpenAck` | [MsgChannelOpenAck](#ibc.core.channel.v1.MsgChannelOpenAck) | [MsgChannelOpenAckResponse](#ibc.core.channel.v1.MsgChannelOpenAckResponse) | ChannelOpenAck defines a rpc handler method for MsgChannelOpenAck. | | -| `ChannelOpenConfirm` | [MsgChannelOpenConfirm](#ibc.core.channel.v1.MsgChannelOpenConfirm) | [MsgChannelOpenConfirmResponse](#ibc.core.channel.v1.MsgChannelOpenConfirmResponse) | ChannelOpenConfirm defines a rpc handler method for MsgChannelOpenConfirm. | | -| `ChannelCloseInit` | [MsgChannelCloseInit](#ibc.core.channel.v1.MsgChannelCloseInit) | [MsgChannelCloseInitResponse](#ibc.core.channel.v1.MsgChannelCloseInitResponse) | ChannelCloseInit defines a rpc handler method for MsgChannelCloseInit. | | -| `ChannelCloseConfirm` | [MsgChannelCloseConfirm](#ibc.core.channel.v1.MsgChannelCloseConfirm) | [MsgChannelCloseConfirmResponse](#ibc.core.channel.v1.MsgChannelCloseConfirmResponse) | ChannelCloseConfirm defines a rpc handler method for MsgChannelCloseConfirm. | | -| `RecvPacket` | [MsgRecvPacket](#ibc.core.channel.v1.MsgRecvPacket) | [MsgRecvPacketResponse](#ibc.core.channel.v1.MsgRecvPacketResponse) | RecvPacket defines a rpc handler method for MsgRecvPacket. | | -| `Timeout` | [MsgTimeout](#ibc.core.channel.v1.MsgTimeout) | [MsgTimeoutResponse](#ibc.core.channel.v1.MsgTimeoutResponse) | Timeout defines a rpc handler method for MsgTimeout. | | -| `TimeoutOnClose` | [MsgTimeoutOnClose](#ibc.core.channel.v1.MsgTimeoutOnClose) | [MsgTimeoutOnCloseResponse](#ibc.core.channel.v1.MsgTimeoutOnCloseResponse) | TimeoutOnClose defines a rpc handler method for MsgTimeoutOnClose. | | -| `Acknowledgement` | [MsgAcknowledgement](#ibc.core.channel.v1.MsgAcknowledgement) | [MsgAcknowledgementResponse](#ibc.core.channel.v1.MsgAcknowledgementResponse) | Acknowledgement defines a rpc handler method for MsgAcknowledgement. | | +| `Channel` | [QueryChannelRequest](#ibc.core.channel.v1.QueryChannelRequest) | [QueryChannelResponse](#ibc.core.channel.v1.QueryChannelResponse) | Channel queries an IBC Channel. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}| +| `Channels` | [QueryChannelsRequest](#ibc.core.channel.v1.QueryChannelsRequest) | [QueryChannelsResponse](#ibc.core.channel.v1.QueryChannelsResponse) | Channels queries all the IBC channels of a chain. | GET|/ibc/core/channel/v1beta1/channels| +| `ConnectionChannels` | [QueryConnectionChannelsRequest](#ibc.core.channel.v1.QueryConnectionChannelsRequest) | [QueryConnectionChannelsResponse](#ibc.core.channel.v1.QueryConnectionChannelsResponse) | ConnectionChannels queries all the channels associated with a connection end. | GET|/ibc/core/channel/v1beta1/connections/{connection}/channels| +| `ChannelClientState` | [QueryChannelClientStateRequest](#ibc.core.channel.v1.QueryChannelClientStateRequest) | [QueryChannelClientStateResponse](#ibc.core.channel.v1.QueryChannelClientStateResponse) | ChannelClientState queries for the client state for the channel associated with the provided channel identifiers. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/client_state| +| `ChannelConsensusState` | [QueryChannelConsensusStateRequest](#ibc.core.channel.v1.QueryChannelConsensusStateRequest) | [QueryChannelConsensusStateResponse](#ibc.core.channel.v1.QueryChannelConsensusStateResponse) | ChannelConsensusState queries for the consensus state for the channel associated with the provided channel identifiers. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/consensus_state/revision/{revision_number}/height/{revision_height}| +| `PacketCommitment` | [QueryPacketCommitmentRequest](#ibc.core.channel.v1.QueryPacketCommitmentRequest) | [QueryPacketCommitmentResponse](#ibc.core.channel.v1.QueryPacketCommitmentResponse) | PacketCommitment queries a stored packet commitment hash. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/{sequence}| +| `PacketCommitments` | [QueryPacketCommitmentsRequest](#ibc.core.channel.v1.QueryPacketCommitmentsRequest) | [QueryPacketCommitmentsResponse](#ibc.core.channel.v1.QueryPacketCommitmentsResponse) | PacketCommitments returns all the packet commitments hashes associated with a channel. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments| +| `PacketReceipt` | [QueryPacketReceiptRequest](#ibc.core.channel.v1.QueryPacketReceiptRequest) | [QueryPacketReceiptResponse](#ibc.core.channel.v1.QueryPacketReceiptResponse) | PacketReceipt queries if a given packet sequence has been received on the queried chain | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_receipts/{sequence}| +| `PacketAcknowledgement` | [QueryPacketAcknowledgementRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementRequest) | [QueryPacketAcknowledgementResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementResponse) | PacketAcknowledgement queries a stored packet acknowledgement hash. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_acks/{sequence}| +| `PacketAcknowledgements` | [QueryPacketAcknowledgementsRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementsRequest) | [QueryPacketAcknowledgementsResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementsResponse) | PacketAcknowledgements returns all the packet acknowledgements associated with a channel. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_acknowledgements| +| `UnreceivedPackets` | [QueryUnreceivedPacketsRequest](#ibc.core.channel.v1.QueryUnreceivedPacketsRequest) | [QueryUnreceivedPacketsResponse](#ibc.core.channel.v1.QueryUnreceivedPacketsResponse) | UnreceivedPackets returns all the unreceived IBC packets associated with a channel and sequences. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/{packet_commitment_sequences}/unreceived_packets| +| `UnreceivedAcks` | [QueryUnreceivedAcksRequest](#ibc.core.channel.v1.QueryUnreceivedAcksRequest) | [QueryUnreceivedAcksResponse](#ibc.core.channel.v1.QueryUnreceivedAcksResponse) | UnreceivedAcks returns all the unreceived IBC acknowledgements associated with a channel and sequences. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/{packet_ack_sequences}/unreceived_acks| +| `NextSequenceReceive` | [QueryNextSequenceReceiveRequest](#ibc.core.channel.v1.QueryNextSequenceReceiveRequest) | [QueryNextSequenceReceiveResponse](#ibc.core.channel.v1.QueryNextSequenceReceiveResponse) | NextSequenceReceive returns the next receive sequence for a given channel. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/next_sequence| - +

      Top

      -## ibc/core/client/v1/genesis.proto +## ibc/core/channel/v1/tx.proto - + -### GenesisMetadata -GenesisMetadata defines the genesis type for metadata that clients may return -with ExportMetadata +### MsgAcknowledgement +MsgAcknowledgement receives incoming IBC acknowledgement | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | store key of metadata without clientID-prefix | -| `value` | [bytes](#bytes) | | metadata value | - - +| `packet` | [Packet](#ibc.core.channel.v1.Packet) | | | +| `acknowledgement` | [bytes](#bytes) | | | +| `proof_acked` | [bytes](#bytes) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `signer` | [string](#string) | | | - -### GenesisState -GenesisState defines the ibc client submodule's genesis state. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `clients` | [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | repeated | client states with their corresponding identifiers | -| `clients_consensus` | [ClientConsensusStates](#ibc.core.client.v1.ClientConsensusStates) | repeated | consensus states from each client | -| `clients_metadata` | [IdentifiedGenesisMetadata](#ibc.core.client.v1.IdentifiedGenesisMetadata) | repeated | metadata from each client | -| `params` | [Params](#ibc.core.client.v1.Params) | | | -| `create_localhost` | [bool](#bool) | | create localhost on initialization | -| `next_client_sequence` | [uint64](#uint64) | | the sequence for the next generated client identifier | +### MsgAcknowledgementResponse +MsgAcknowledgementResponse defines the Msg/Acknowledgement response type. - + -### IdentifiedGenesisMetadata -IdentifiedGenesisMetadata has the client metadata with the corresponding client id. +### MsgChannelCloseConfirm +MsgChannelCloseConfirm defines a msg sent by a Relayer to Chain B +to acknowledge the change of channel state to CLOSED on Chain A. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `client_metadata` | [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) | repeated | | - - +| `port_id` | [string](#string) | | | +| `channel_id` | [string](#string) | | | +| `proof_init` | [bytes](#bytes) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `signer` | [string](#string) | | | - - - - + +### MsgChannelCloseConfirmResponse +MsgChannelCloseConfirmResponse defines the Msg/ChannelCloseConfirm response type. - -

      Top

      -## ibc/core/client/v1/query.proto - + -### QueryClientParamsRequest -QueryClientParamsRequest is the request type for the Query/ClientParams RPC method. +### MsgChannelCloseInit +MsgChannelCloseInit defines a msg sent by a Relayer to Chain A +to close a channel with Chain B. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `port_id` | [string](#string) | | | +| `channel_id` | [string](#string) | | | +| `signer` | [string](#string) | | | - -### QueryClientParamsResponse -QueryClientParamsResponse is the response type for the Query/ClientParams RPC method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params` | [Params](#ibc.core.client.v1.Params) | | params defines the parameters of the module. | +### MsgChannelCloseInitResponse +MsgChannelCloseInitResponse defines the Msg/ChannelCloseInit response type. - + -### QueryClientStateRequest -QueryClientStateRequest is the request type for the Query/ClientState RPC -method +### MsgChannelOpenAck +MsgChannelOpenAck defines a msg sent by a Relayer to Chain A to acknowledge +the change of channel state to TRYOPEN on Chain B. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client state unique identifier | - - +| `port_id` | [string](#string) | | | +| `channel_id` | [string](#string) | | | +| `counterparty_channel_id` | [string](#string) | | | +| `counterparty_version` | [string](#string) | | | +| `proof_try` | [bytes](#bytes) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `signer` | [string](#string) | | | - -### QueryClientStateResponse -QueryClientStateResponse is the response type for the Query/ClientState RPC -method. Besides the client state, it includes a proof and the height from -which the proof was retrieved. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | client state associated with the request identifier | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | +### MsgChannelOpenAckResponse +MsgChannelOpenAckResponse defines the Msg/ChannelOpenAck response type. - + -### QueryClientStatesRequest -QueryClientStatesRequest is the request type for the Query/ClientStates RPC -method +### MsgChannelOpenConfirm +MsgChannelOpenConfirm defines a msg sent by a Relayer to Chain B to +acknowledge the change of channel state to OPEN on Chain A. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - - +| `port_id` | [string](#string) | | | +| `channel_id` | [string](#string) | | | +| `proof_ack` | [bytes](#bytes) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `signer` | [string](#string) | | | - -### QueryClientStatesResponse -QueryClientStatesResponse is the response type for the Query/ClientStates RPC -method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_states` | [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | repeated | list of stored ClientStates of the chain. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | +### MsgChannelOpenConfirmResponse +MsgChannelOpenConfirmResponse defines the Msg/ChannelOpenConfirm response type. - + -### QueryConsensusStateRequest -QueryConsensusStateRequest is the request type for the Query/ConsensusState -RPC method. Besides the consensus state, it includes a proof and the height -from which the proof was retrieved. +### MsgChannelOpenInit +MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It +is called by a relayer on Chain A. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier | -| `revision_number` | [uint64](#uint64) | | consensus state revision number | -| `revision_height` | [uint64](#uint64) | | consensus state revision height | -| `latest_height` | [bool](#bool) | | latest_height overrrides the height field and queries the latest stored ConsensusState | - - +| `port_id` | [string](#string) | | | +| `channel` | [Channel](#ibc.core.channel.v1.Channel) | | | +| `signer` | [string](#string) | | | - -### QueryConsensusStateResponse -QueryConsensusStateResponse is the response type for the Query/ConsensusState -RPC method + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the client identifier at the given height | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | +### MsgChannelOpenInitResponse +MsgChannelOpenInitResponse defines the Msg/ChannelOpenInit response type. - + -### QueryConsensusStatesRequest -QueryConsensusStatesRequest is the request type for the Query/ConsensusStates -RPC method. +### MsgChannelOpenTry +MsgChannelOpenInit defines a msg sent by a Relayer to try to open a channel +on Chain B. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | +| `port_id` | [string](#string) | | | +| `previous_channel_id` | [string](#string) | | in the case of crossing hello's, when both chains call OpenInit, we need the channel identifier of the previous channel in state INIT | +| `channel` | [Channel](#ibc.core.channel.v1.Channel) | | | +| `counterparty_version` | [string](#string) | | | +| `proof_init` | [bytes](#bytes) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `signer` | [string](#string) | | | - + -### QueryConsensusStatesResponse -QueryConsensusStatesResponse is the response type for the -Query/ConsensusStates RPC method +### MsgChannelOpenTryResponse +MsgChannelOpenTryResponse defines the Msg/ChannelOpenTry response type. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `consensus_states` | [ConsensusStateWithHeight](#ibc.core.client.v1.ConsensusStateWithHeight) | repeated | consensus states associated with the identifier | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | + - +### MsgRecvPacket +MsgRecvPacket receives incoming IBC packet - - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `packet` | [Packet](#ibc.core.channel.v1.Packet) | | | +| `proof_commitment` | [bytes](#bytes) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `signer` | [string](#string) | | | - -### Query -Query provides defines the gRPC querier service -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `ClientState` | [QueryClientStateRequest](#ibc.core.client.v1.QueryClientStateRequest) | [QueryClientStateResponse](#ibc.core.client.v1.QueryClientStateResponse) | ClientState queries an IBC light client. | GET|/ibc/core/client/v1beta1/client_states/{client_id}| -| `ClientStates` | [QueryClientStatesRequest](#ibc.core.client.v1.QueryClientStatesRequest) | [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse) | ClientStates queries all the IBC light clients of a chain. | GET|/ibc/core/client/v1beta1/client_states| -| `ConsensusState` | [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest) | [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) | ConsensusState queries a consensus state associated with a client state at a given height. | GET|/ibc/core/client/v1beta1/consensus_states/{client_id}/revision/{revision_number}/height/{revision_height}| -| `ConsensusStates` | [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) | [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) | ConsensusStates queries all the consensus state associated with a given client. | GET|/ibc/core/client/v1beta1/consensus_states/{client_id}| -| `ClientParams` | [QueryClientParamsRequest](#ibc.core.client.v1.QueryClientParamsRequest) | [QueryClientParamsResponse](#ibc.core.client.v1.QueryClientParamsResponse) | ClientParams queries all parameters of the ibc client. | GET|/ibc/client/v1beta1/params| - + +### MsgRecvPacketResponse +MsgRecvPacketResponse defines the Msg/RecvPacket response type. - -

      Top

      -## ibc/core/client/v1/tx.proto - -### MsgCreateClient -MsgCreateClient defines a message to create an IBC client + + +### MsgTimeout +MsgTimeout receives timed-out packet | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | light client state | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the client that corresponds to a given height. | -| `signer` | [string](#string) | | signer address | - - - +| `packet` | [Packet](#ibc.core.channel.v1.Packet) | | | +| `proof_unreceived` | [bytes](#bytes) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `next_sequence_recv` | [uint64](#uint64) | | | +| `signer` | [string](#string) | | | - -### MsgCreateClientResponse -MsgCreateClientResponse defines the Msg/CreateClient response type. + +### MsgTimeoutOnClose +MsgTimeoutOnClose timed-out packet upon counterparty channel closure. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `packet` | [Packet](#ibc.core.channel.v1.Packet) | | | +| `proof_unreceived` | [bytes](#bytes) | | | +| `proof_close` | [bytes](#bytes) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `next_sequence_recv` | [uint64](#uint64) | | | +| `signer` | [string](#string) | | | - -### MsgSubmitMisbehaviour -MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for -light client misbehaviour. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client unique identifier | -| `misbehaviour` | [google.protobuf.Any](#google.protobuf.Any) | | misbehaviour used for freezing the light client | -| `signer` | [string](#string) | | signer address | + +### MsgTimeoutOnCloseResponse +MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type. - -### MsgSubmitMisbehaviourResponse -MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response type. + +### MsgTimeoutResponse +MsgTimeoutResponse defines the Msg/Timeout response type. - -### MsgUpdateClient -MsgUpdateClient defines an sdk.Msg to update a IBC client state using -the given header. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client unique identifier | -| `header` | [google.protobuf.Any](#google.protobuf.Any) | | header to update the light client | -| `signer` | [string](#string) | | signer address | + + + +### Msg +Msg defines the ibc/channel Msg service. +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `ChannelOpenInit` | [MsgChannelOpenInit](#ibc.core.channel.v1.MsgChannelOpenInit) | [MsgChannelOpenInitResponse](#ibc.core.channel.v1.MsgChannelOpenInitResponse) | ChannelOpenInit defines a rpc handler method for MsgChannelOpenInit. | | +| `ChannelOpenTry` | [MsgChannelOpenTry](#ibc.core.channel.v1.MsgChannelOpenTry) | [MsgChannelOpenTryResponse](#ibc.core.channel.v1.MsgChannelOpenTryResponse) | ChannelOpenTry defines a rpc handler method for MsgChannelOpenTry. | | +| `ChannelOpenAck` | [MsgChannelOpenAck](#ibc.core.channel.v1.MsgChannelOpenAck) | [MsgChannelOpenAckResponse](#ibc.core.channel.v1.MsgChannelOpenAckResponse) | ChannelOpenAck defines a rpc handler method for MsgChannelOpenAck. | | +| `ChannelOpenConfirm` | [MsgChannelOpenConfirm](#ibc.core.channel.v1.MsgChannelOpenConfirm) | [MsgChannelOpenConfirmResponse](#ibc.core.channel.v1.MsgChannelOpenConfirmResponse) | ChannelOpenConfirm defines a rpc handler method for MsgChannelOpenConfirm. | | +| `ChannelCloseInit` | [MsgChannelCloseInit](#ibc.core.channel.v1.MsgChannelCloseInit) | [MsgChannelCloseInitResponse](#ibc.core.channel.v1.MsgChannelCloseInitResponse) | ChannelCloseInit defines a rpc handler method for MsgChannelCloseInit. | | +| `ChannelCloseConfirm` | [MsgChannelCloseConfirm](#ibc.core.channel.v1.MsgChannelCloseConfirm) | [MsgChannelCloseConfirmResponse](#ibc.core.channel.v1.MsgChannelCloseConfirmResponse) | ChannelCloseConfirm defines a rpc handler method for MsgChannelCloseConfirm. | | +| `RecvPacket` | [MsgRecvPacket](#ibc.core.channel.v1.MsgRecvPacket) | [MsgRecvPacketResponse](#ibc.core.channel.v1.MsgRecvPacketResponse) | RecvPacket defines a rpc handler method for MsgRecvPacket. | | +| `Timeout` | [MsgTimeout](#ibc.core.channel.v1.MsgTimeout) | [MsgTimeoutResponse](#ibc.core.channel.v1.MsgTimeoutResponse) | Timeout defines a rpc handler method for MsgTimeout. | | +| `TimeoutOnClose` | [MsgTimeoutOnClose](#ibc.core.channel.v1.MsgTimeoutOnClose) | [MsgTimeoutOnCloseResponse](#ibc.core.channel.v1.MsgTimeoutOnCloseResponse) | TimeoutOnClose defines a rpc handler method for MsgTimeoutOnClose. | | +| `Acknowledgement` | [MsgAcknowledgement](#ibc.core.channel.v1.MsgAcknowledgement) | [MsgAcknowledgementResponse](#ibc.core.channel.v1.MsgAcknowledgementResponse) | Acknowledgement defines a rpc handler method for MsgAcknowledgement. | | - + -### MsgUpdateClientResponse -MsgUpdateClientResponse defines the Msg/UpdateClient response type. + +

      Top

      +## ibc/core/channel/v1/genesis.proto - + -### MsgUpgradeClient -MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state +### GenesisState +GenesisState defines the ibc channel submodule's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client unique identifier | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | upgraded client state | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | upgraded consensus state, only contains enough information to serve as a basis of trust in update logic | -| `proof_upgrade_client` | [bytes](#bytes) | | proof that old chain committed to new client | -| `proof_upgrade_consensus_state` | [bytes](#bytes) | | proof that old chain committed to new consensus state | -| `signer` | [string](#string) | | signer address | +| `channels` | [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) | repeated | | +| `acknowledgements` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | +| `commitments` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | +| `receipts` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | +| `send_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | +| `recv_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | +| `ack_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | +| `next_channel_sequence` | [uint64](#uint64) | | the sequence for the next generated channel identifier | - + -### MsgUpgradeClientResponse -MsgUpgradeClientResponse defines the Msg/UpgradeClient response type. +### PacketSequence +PacketSequence defines the genesis type necessary to retrieve and store +next send and receive sequences. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `port_id` | [string](#string) | | | +| `channel_id` | [string](#string) | | | +| `sequence` | [uint64](#uint64) | | | @@ -9168,19 +9513,6 @@ MsgUpgradeClientResponse defines the Msg/UpgradeClient response type. - - - -### Msg -Msg defines the ibc/client Msg service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `CreateClient` | [MsgCreateClient](#ibc.core.client.v1.MsgCreateClient) | [MsgCreateClientResponse](#ibc.core.client.v1.MsgCreateClientResponse) | CreateClient defines a rpc handler method for MsgCreateClient. | | -| `UpdateClient` | [MsgUpdateClient](#ibc.core.client.v1.MsgUpdateClient) | [MsgUpdateClientResponse](#ibc.core.client.v1.MsgUpdateClientResponse) | UpdateClient defines a rpc handler method for MsgUpdateClient. | | -| `UpgradeClient` | [MsgUpgradeClient](#ibc.core.client.v1.MsgUpgradeClient) | [MsgUpgradeClientResponse](#ibc.core.client.v1.MsgUpgradeClientResponse) | UpgradeClient defines a rpc handler method for MsgUpgradeClient. | | -| `SubmitMisbehaviour` | [MsgSubmitMisbehaviour](#ibc.core.client.v1.MsgSubmitMisbehaviour) | [MsgSubmitMisbehaviourResponse](#ibc.core.client.v1.MsgSubmitMisbehaviourResponse) | SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour. | | - @@ -9409,39 +9741,6 @@ INIT, TRYOPEN, OPEN or UNINITIALIZED. - -

      Top

      - -## ibc/core/connection/v1/genesis.proto - - - - - -### GenesisState -GenesisState defines the ibc connection submodule's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connections` | [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) | repeated | | -| `client_connection_paths` | [ConnectionPaths](#ibc.core.connection.v1.ConnectionPaths) | repeated | | -| `next_connection_sequence` | [uint64](#uint64) | | the sequence for the next generated connection identifier | - - - - - - - - - - - - - - -

      Top

      @@ -9737,126 +10036,281 @@ initialize a connection with Chain B. - + + +### MsgConnectionOpenInitResponse +MsgConnectionOpenInitResponse defines the Msg/ConnectionOpenInit response type. + + + + + + + + +### MsgConnectionOpenTry +MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a +connection on Chain B. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | | +| `previous_connection_id` | [string](#string) | | in the case of crossing hello's, when both chains call OpenInit, we need the connection identifier of the previous connection in state INIT | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | | +| `delay_period` | [uint64](#uint64) | | | +| `counterparty_versions` | [Version](#ibc.core.connection.v1.Version) | repeated | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `proof_init` | [bytes](#bytes) | | proof of the initialization the connection on Chain A: `UNITIALIZED -> INIT` | +| `proof_client` | [bytes](#bytes) | | proof of client state included in message | +| `proof_consensus` | [bytes](#bytes) | | proof of client consensus state | +| `consensus_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `signer` | [string](#string) | | | + + + + + + + + +### MsgConnectionOpenTryResponse +MsgConnectionOpenTryResponse defines the Msg/ConnectionOpenTry response type. + + + + + + + + + + + + + + +### Msg +Msg defines the ibc/connection Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `ConnectionOpenInit` | [MsgConnectionOpenInit](#ibc.core.connection.v1.MsgConnectionOpenInit) | [MsgConnectionOpenInitResponse](#ibc.core.connection.v1.MsgConnectionOpenInitResponse) | ConnectionOpenInit defines a rpc handler method for MsgConnectionOpenInit. | | +| `ConnectionOpenTry` | [MsgConnectionOpenTry](#ibc.core.connection.v1.MsgConnectionOpenTry) | [MsgConnectionOpenTryResponse](#ibc.core.connection.v1.MsgConnectionOpenTryResponse) | ConnectionOpenTry defines a rpc handler method for MsgConnectionOpenTry. | | +| `ConnectionOpenAck` | [MsgConnectionOpenAck](#ibc.core.connection.v1.MsgConnectionOpenAck) | [MsgConnectionOpenAckResponse](#ibc.core.connection.v1.MsgConnectionOpenAckResponse) | ConnectionOpenAck defines a rpc handler method for MsgConnectionOpenAck. | | +| `ConnectionOpenConfirm` | [MsgConnectionOpenConfirm](#ibc.core.connection.v1.MsgConnectionOpenConfirm) | [MsgConnectionOpenConfirmResponse](#ibc.core.connection.v1.MsgConnectionOpenConfirmResponse) | ConnectionOpenConfirm defines a rpc handler method for MsgConnectionOpenConfirm. | | + + + + + + +

      Top

      + +## ibc/core/connection/v1/genesis.proto + + + + + +### GenesisState +GenesisState defines the ibc connection submodule's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `connections` | [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) | repeated | | +| `client_connection_paths` | [ConnectionPaths](#ibc.core.connection.v1.ConnectionPaths) | repeated | | +| `next_connection_sequence` | [uint64](#uint64) | | the sequence for the next generated connection identifier | + + + + + + + + + + + + + + + + +

      Top

      + +## ibc/core/types/v1/genesis.proto + + + + + +### GenesisState +GenesisState defines the ibc module's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_genesis` | [ibc.core.client.v1.GenesisState](#ibc.core.client.v1.GenesisState) | | ICS002 - Clients genesis state | +| `connection_genesis` | [ibc.core.connection.v1.GenesisState](#ibc.core.connection.v1.GenesisState) | | ICS003 - Connections genesis state | +| `channel_genesis` | [ibc.core.channel.v1.GenesisState](#ibc.core.channel.v1.GenesisState) | | ICS004 - Channel genesis state | + + + + + + + + + + + + + + + + +

      Top

      + +## ibc/lightclients/localhost/v1/localhost.proto + + + + -### MsgConnectionOpenInitResponse -MsgConnectionOpenInitResponse defines the Msg/ConnectionOpenInit response type. +### ClientState +ClientState defines a loopback (localhost) client. It requires (read-only) +access to keys outside the client prefix. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `chain_id` | [string](#string) | | self chain ID | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | self latest block height | - -### MsgConnectionOpenTry -MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a -connection on Chain B. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `previous_connection_id` | [string](#string) | | in the case of crossing hello's, when both chains call OpenInit, we need the connection identifier of the previous connection in state INIT | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | | -| `delay_period` | [uint64](#uint64) | | | -| `counterparty_versions` | [Version](#ibc.core.connection.v1.Version) | repeated | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `proof_init` | [bytes](#bytes) | | proof of the initialization the connection on Chain A: `UNITIALIZED -> INIT` | -| `proof_client` | [bytes](#bytes) | | proof of client state included in message | -| `proof_consensus` | [bytes](#bytes) | | proof of client consensus state | -| `consensus_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | + + + +

      Top

      +## ibc/lightclients/tendermint/v1/tendermint.proto - -### MsgConnectionOpenTryResponse -MsgConnectionOpenTryResponse defines the Msg/ConnectionOpenTry response type. + +### ClientState +ClientState from Tendermint tracks the current validator set, latest height, +and a possible frozen height. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `chain_id` | [string](#string) | | | +| `trust_level` | [Fraction](#ibc.lightclients.tendermint.v1.Fraction) | | | +| `trusting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | duration of the period since the LastestTimestamp during which the submitted headers are valid for upgrade | +| `unbonding_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | duration of the staking unbonding period | +| `max_clock_drift` | [google.protobuf.Duration](#google.protobuf.Duration) | | defines how much new (untrusted) header's Time can drift into the future. | +| `frozen_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Block height when the client was frozen due to a misbehaviour | +| `latest_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Latest height the client was updated to | +| `proof_specs` | [ics23.ProofSpec](#ics23.ProofSpec) | repeated | Proof specifications used in verifying counterparty state | +| `upgrade_path` | [string](#string) | repeated | Path at which next upgraded client will be committed. Each element corresponds to the key for a single CommitmentProof in the chained proof. NOTE: ClientState must stored under `{upgradePath}/{upgradeHeight}/clientState` ConsensusState must be stored under `{upgradepath}/{upgradeHeight}/consensusState` For SDK chains using the default upgrade module, upgrade_path should be []string{"upgrade", "upgradedIBCState"}` | +| `allow_update_after_expiry` | [bool](#bool) | | This flag, when set to true, will allow governance to recover a client which has expired | +| `allow_update_after_misbehaviour` | [bool](#bool) | | This flag, when set to true, will allow governance to unfreeze a client whose chain has experienced a misbehaviour event | - - - - -### Msg -Msg defines the ibc/connection Msg service. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `ConnectionOpenInit` | [MsgConnectionOpenInit](#ibc.core.connection.v1.MsgConnectionOpenInit) | [MsgConnectionOpenInitResponse](#ibc.core.connection.v1.MsgConnectionOpenInitResponse) | ConnectionOpenInit defines a rpc handler method for MsgConnectionOpenInit. | | -| `ConnectionOpenTry` | [MsgConnectionOpenTry](#ibc.core.connection.v1.MsgConnectionOpenTry) | [MsgConnectionOpenTryResponse](#ibc.core.connection.v1.MsgConnectionOpenTryResponse) | ConnectionOpenTry defines a rpc handler method for MsgConnectionOpenTry. | | -| `ConnectionOpenAck` | [MsgConnectionOpenAck](#ibc.core.connection.v1.MsgConnectionOpenAck) | [MsgConnectionOpenAckResponse](#ibc.core.connection.v1.MsgConnectionOpenAckResponse) | ConnectionOpenAck defines a rpc handler method for MsgConnectionOpenAck. | | -| `ConnectionOpenConfirm` | [MsgConnectionOpenConfirm](#ibc.core.connection.v1.MsgConnectionOpenConfirm) | [MsgConnectionOpenConfirmResponse](#ibc.core.connection.v1.MsgConnectionOpenConfirmResponse) | ConnectionOpenConfirm defines a rpc handler method for MsgConnectionOpenConfirm. | | +### ConsensusState +ConsensusState defines the consensus state from Tendermint. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `timestamp` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | timestamp that corresponds to the block height in which the ConsensusState was stored. | +| `root` | [ibc.core.commitment.v1.MerkleRoot](#ibc.core.commitment.v1.MerkleRoot) | | commitment root (i.e app hash) | +| `next_validators_hash` | [bytes](#bytes) | | | - -

      Top

      -## ibc/core/types/v1/genesis.proto - + -### GenesisState -GenesisState defines the ibc module's genesis state. +### Fraction +Fraction defines the protobuf message type for tmmath.Fraction that only supports positive values. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_genesis` | [ibc.core.client.v1.GenesisState](#ibc.core.client.v1.GenesisState) | | ICS002 - Clients genesis state | -| `connection_genesis` | [ibc.core.connection.v1.GenesisState](#ibc.core.connection.v1.GenesisState) | | ICS003 - Connections genesis state | -| `channel_genesis` | [ibc.core.channel.v1.GenesisState](#ibc.core.channel.v1.GenesisState) | | ICS004 - Channel genesis state | +| `numerator` | [uint64](#uint64) | | | +| `denominator` | [uint64](#uint64) | | | - - + - +### Header +Header defines the Tendermint client consensus Header. +It encapsulates all the information necessary to update from a trusted +Tendermint ConsensusState. The inclusion of TrustedHeight and +TrustedValidators allows this update to process correctly, so long as the +ConsensusState for the TrustedHeight exists, this removes race conditions +among relayers The SignedHeader and ValidatorSet are the new untrusted update +fields for the client. The TrustedHeight is the height of a stored +ConsensusState on the client that will be used to verify the new untrusted +header. The Trusted ConsensusState must be within the unbonding period of +current time in order to correctly verify, and the TrustedValidators must +hash to TrustedConsensusState.NextValidatorsHash since that is the last +trusted validator set at the TrustedHeight. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `signed_header` | [tendermint.types.SignedHeader](#tendermint.types.SignedHeader) | | | +| `validator_set` | [tendermint.types.ValidatorSet](#tendermint.types.ValidatorSet) | | | +| `trusted_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `trusted_validators` | [tendermint.types.ValidatorSet](#tendermint.types.ValidatorSet) | | | - -

      Top

      -## ibc/lightclients/localhost/v1/localhost.proto - + -### ClientState -ClientState defines a loopback (localhost) client. It requires (read-only) -access to keys outside the client prefix. +### Misbehaviour +Misbehaviour is a wrapper over two conflicting Headers +that implements Misbehaviour interface expected by ICS-02 | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `chain_id` | [string](#string) | | self chain ID | -| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | self latest block height | +| `client_id` | [string](#string) | | | +| `header_1` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | +| `header_2` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | @@ -10189,128 +10643,6 @@ data sign byte encodings. - -

      Top

      - -## ibc/lightclients/tendermint/v1/tendermint.proto - - - - - -### ClientState -ClientState from Tendermint tracks the current validator set, latest height, -and a possible frozen height. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `chain_id` | [string](#string) | | | -| `trust_level` | [Fraction](#ibc.lightclients.tendermint.v1.Fraction) | | | -| `trusting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | duration of the period since the LastestTimestamp during which the submitted headers are valid for upgrade | -| `unbonding_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | duration of the staking unbonding period | -| `max_clock_drift` | [google.protobuf.Duration](#google.protobuf.Duration) | | defines how much new (untrusted) header's Time can drift into the future. | -| `frozen_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Block height when the client was frozen due to a misbehaviour | -| `latest_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Latest height the client was updated to | -| `proof_specs` | [ics23.ProofSpec](#ics23.ProofSpec) | repeated | Proof specifications used in verifying counterparty state | -| `upgrade_path` | [string](#string) | repeated | Path at which next upgraded client will be committed. Each element corresponds to the key for a single CommitmentProof in the chained proof. NOTE: ClientState must stored under `{upgradePath}/{upgradeHeight}/clientState` ConsensusState must be stored under `{upgradepath}/{upgradeHeight}/consensusState` For SDK chains using the default upgrade module, upgrade_path should be []string{"upgrade", "upgradedIBCState"}` | -| `allow_update_after_expiry` | [bool](#bool) | | This flag, when set to true, will allow governance to recover a client which has expired | -| `allow_update_after_misbehaviour` | [bool](#bool) | | This flag, when set to true, will allow governance to unfreeze a client whose chain has experienced a misbehaviour event | - - - - - - - - -### ConsensusState -ConsensusState defines the consensus state from Tendermint. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `timestamp` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | timestamp that corresponds to the block height in which the ConsensusState was stored. | -| `root` | [ibc.core.commitment.v1.MerkleRoot](#ibc.core.commitment.v1.MerkleRoot) | | commitment root (i.e app hash) | -| `next_validators_hash` | [bytes](#bytes) | | | - - - - - - - - -### Fraction -Fraction defines the protobuf message type for tmmath.Fraction that only supports positive values. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `numerator` | [uint64](#uint64) | | | -| `denominator` | [uint64](#uint64) | | | - - - - - - - - -### Header -Header defines the Tendermint client consensus Header. -It encapsulates all the information necessary to update from a trusted -Tendermint ConsensusState. The inclusion of TrustedHeight and -TrustedValidators allows this update to process correctly, so long as the -ConsensusState for the TrustedHeight exists, this removes race conditions -among relayers The SignedHeader and ValidatorSet are the new untrusted update -fields for the client. The TrustedHeight is the height of a stored -ConsensusState on the client that will be used to verify the new untrusted -header. The Trusted ConsensusState must be within the unbonding period of -current time in order to correctly verify, and the TrustedValidators must -hash to TrustedConsensusState.NextValidatorsHash since that is the last -trusted validator set at the TrustedHeight. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `signed_header` | [tendermint.types.SignedHeader](#tendermint.types.SignedHeader) | | | -| `validator_set` | [tendermint.types.ValidatorSet](#tendermint.types.ValidatorSet) | | | -| `trusted_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `trusted_validators` | [tendermint.types.ValidatorSet](#tendermint.types.ValidatorSet) | | | - - - - - - - - -### Misbehaviour -Misbehaviour is a wrapper over two conflicting Headers -that implements Misbehaviour interface expected by ICS-02 - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `header_1` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | -| `header_2` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | - - - - - - - - - - - - - - - ## Scalar Value Types | .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby | diff --git a/proto/cosmos/feegrant/v1beta1/feegrant.proto b/proto/cosmos/feegrant/v1beta1/feegrant.proto new file mode 100644 index 000000000000..534de582d977 --- /dev/null +++ b/proto/cosmos/feegrant/v1beta1/feegrant.proto @@ -0,0 +1,81 @@ +syntax = "proto3"; +package cosmos.feegrant.v1beta1; + +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; +import "cosmos_proto/cosmos.proto"; +import "cosmos/base/v1beta1/coin.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/duration.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/feegrant/types"; + +// BasicFeeAllowance implements FeeAllowance with a one-time grant of tokens +// that optionally expires. The delegatee can use up to SpendLimit to cover fees. +message BasicFeeAllowance { + option (cosmos_proto.implements_interface) = "FeeAllowanceI"; + + // spend_limit specifies the maximum amount of tokens that can be spent + // by this allowance and will be updated as tokens are spent. If it is + // empty, there is no spend limit and any amount of coins can be spent. + repeated cosmos.base.v1beta1.Coin spend_limit = 1 + [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; + + // expiration specifies an optional time when this allowance expires + ExpiresAt expiration = 2 [(gogoproto.nullable) = false]; +} + +// PeriodicFeeAllowance extends FeeAllowance to allow for both a maximum cap, +// as well as a limit per time period. +message PeriodicFeeAllowance { + option (cosmos_proto.implements_interface) = "FeeAllowanceI"; + + // basic specifies a struct of `BasicFeeAllowance` + BasicFeeAllowance basic = 1 [(gogoproto.nullable) = false]; + + // period specifies the time duration in which period_spend_limit coins can + // be spent before that allowance is reset + Duration period = 2 [(gogoproto.nullable) = false]; + + // period_spend_limit specifies the maximum number of coins that can be spent + // in the period + repeated cosmos.base.v1beta1.Coin period_spend_limit = 3 + [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; + + // period_can_spend is the number of coins left to be spent before the period_reset time + repeated cosmos.base.v1beta1.Coin period_can_spend = 4 + [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; + + // period_reset is the time at which this period resets and a new one begins, + // it is calculated from the start time of the first transaction after the + // last period ended + ExpiresAt period_reset = 5 [(gogoproto.nullable) = false]; +} + +// Duration is a span of a clock time or number of blocks. +// This is designed to be added to an ExpiresAt struct. +message Duration { + // sum is the oneof that represents either duration or block + oneof sum { + google.protobuf.Duration duration = 1 [(gogoproto.stdduration) = true]; + uint64 blocks = 2; + } +} + +// ExpiresAt is a point in time where something expires. +// It may be *either* block time or block height +message ExpiresAt { + // sum is the oneof that represents either time or height + oneof sum { + google.protobuf.Timestamp time = 1 [(gogoproto.stdtime) = true]; + int64 height = 2; + } +} + +// FeeAllowanceGrant is stored in the KVStore to record a grant with full context +message FeeAllowanceGrant { + + string granter = 1; + string grantee = 2; + google.protobuf.Any allowance = 3 [(cosmos_proto.accepts_interface) = "FeeAllowanceI"]; +} diff --git a/proto/cosmos/feegrant/v1beta1/genesis.proto b/proto/cosmos/feegrant/v1beta1/genesis.proto new file mode 100644 index 000000000000..a021ea61dfc7 --- /dev/null +++ b/proto/cosmos/feegrant/v1beta1/genesis.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; +package cosmos.feegrant.v1beta1; + +import "gogoproto/gogo.proto"; +import "cosmos/feegrant/v1beta1/feegrant.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/feegrant/types"; + +// GenesisState contains a set of fee allowances, persisted from the store +message GenesisState { + repeated FeeAllowanceGrant fee_allowances = 1 [(gogoproto.nullable) = false]; +} diff --git a/proto/cosmos/feegrant/v1beta1/query.proto b/proto/cosmos/feegrant/v1beta1/query.proto new file mode 100644 index 000000000000..42d5f302005f --- /dev/null +++ b/proto/cosmos/feegrant/v1beta1/query.proto @@ -0,0 +1,52 @@ +syntax = "proto3"; +package cosmos.feegrant.v1beta1; + +import "gogoproto/gogo.proto"; +import "cosmos/feegrant/v1beta1/feegrant.proto"; +import "cosmos/base/query/v1beta1/pagination.proto"; +import "google/api/annotations.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/feegrant/types"; + +// Query defines the gRPC querier service. +service Query { + + // FeeAllowance returns fee granted to the grantee by the granter. + rpc FeeAllowance(QueryFeeAllowanceRequest) returns (QueryFeeAllowanceResponse) { + option (google.api.http).get = "/cosmos/feegrant/v1beta1/fee_allowance/{granter}/{grantee}"; + } + + // FeeAllowances returns all the grants for address. + rpc FeeAllowances(QueryFeeAllowancesRequest) returns (QueryFeeAllowancesResponse) { + option (google.api.http).get = "/cosmos/feegrant/v1beta1/fee_allowances/{grantee}"; + } +} + +// QueryFeeAllowanceRequest is the request type for the Query/FeeAllowance RPC method. +message QueryFeeAllowanceRequest { + string granter = 1; + string grantee = 2; +} + +// QueryFeeAllowanceResponse is the response type for the Query/FeeAllowance RPC method. +message QueryFeeAllowanceResponse { + // fee_allowance is a fee_allowance granted for grantee by granter. + cosmos.feegrant.v1beta1.FeeAllowanceGrant fee_allowance = 1; +} + +// QueryFeeAllowancesRequest is the request type for the Query/FeeAllowances RPC method. +message QueryFeeAllowancesRequest { + string grantee = 1; + + // pagination defines an pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryFeeAllowancesResponse is the response type for the Query/FeeAllowances RPC method. +message QueryFeeAllowancesResponse { + // fee_allowances are fee_allowance's granted for grantee by granter. + repeated cosmos.feegrant.v1beta1.FeeAllowanceGrant fee_allowances = 1; + + // pagination defines an pagination for the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} diff --git a/proto/cosmos/feegrant/v1beta1/tx.proto b/proto/cosmos/feegrant/v1beta1/tx.proto new file mode 100644 index 000000000000..a36f358f2503 --- /dev/null +++ b/proto/cosmos/feegrant/v1beta1/tx.proto @@ -0,0 +1,40 @@ +syntax = "proto3"; +package cosmos.feegrant.v1beta1; + +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; +import "cosmos_proto/cosmos.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/feegrant/types"; + +// Msg defines the feegrant msg service. +service Msg { + + // GrantFeeAllowance grants fee allowance to the grantee on the granter's + // account with the provided expiration time. + rpc GrantFeeAllowance(MsgGrantFeeAllowance) returns (MsgGrantFeeAllowanceResponse); + + // RevokeFeeAllowance revokes any fee allowance of granter's account that + // has been granted to the grantee. + rpc RevokeFeeAllowance(MsgRevokeFeeAllowance) returns (MsgRevokeFeeAllowanceResponse); +} + +// MsgGrantFeeAllowance adds permission for Grantee to spend up to Allowance +// of fees from the account of Granter. +message MsgGrantFeeAllowance { + string granter = 1; + string grantee = 2; + google.protobuf.Any allowance = 3 [(cosmos_proto.accepts_interface) = "FeeAllowanceI"]; +} + +// MsgGrantFeeAllowanceResponse defines the Msg/GrantFeeAllowanceResponse response type. +message MsgGrantFeeAllowanceResponse {} + +// MsgRevokeFeeAllowance removes any existing FeeAllowance from Granter to Grantee. +message MsgRevokeFeeAllowance { + string granter = 1; + string grantee = 2; +} + +// MsgRevokeFeeAllowanceResponse defines the Msg/RevokeFeeAllowanceResponse response type. +message MsgRevokeFeeAllowanceResponse {} diff --git a/simapp/app.go b/simapp/app.go index 5e9c3e29e163..23ced043d047 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -55,6 +55,10 @@ import ( "github.com/cosmos/cosmos-sdk/x/evidence" evidencekeeper "github.com/cosmos/cosmos-sdk/x/evidence/keeper" evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" + feegrant "github.com/cosmos/cosmos-sdk/x/feegrant" + feegrantante "github.com/cosmos/cosmos-sdk/x/feegrant/ante" + feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + feegranttypes "github.com/cosmos/cosmos-sdk/x/feegrant/types" "github.com/cosmos/cosmos-sdk/x/genutil" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" "github.com/cosmos/cosmos-sdk/x/gov" @@ -120,6 +124,7 @@ var ( crisis.AppModuleBasic{}, slashing.AppModuleBasic{}, ibc.AppModuleBasic{}, + feegrant.AppModuleBasic{}, upgrade.AppModuleBasic{}, evidence.AppModuleBasic{}, transfer.AppModuleBasic{}, @@ -181,6 +186,7 @@ type SimApp struct { IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly EvidenceKeeper evidencekeeper.Keeper TransferKeeper ibctransferkeeper.Keeper + FeeGrantKeeper feegrantkeeper.Keeper // make scoped keepers public for test purposes ScopedIBCKeeper capabilitykeeper.ScopedKeeper @@ -222,7 +228,7 @@ func NewSimApp( keys := sdk.NewKVStoreKeys( authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, - govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, + govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, feegranttypes.StoreKey, evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, authztypes.StoreKey, ) @@ -277,6 +283,8 @@ func NewSimApp( app.CrisisKeeper = crisiskeeper.NewKeeper( app.GetSubspace(crisistypes.ModuleName), invCheckPeriod, app.BankKeeper, authtypes.FeeCollectorName, ) + + app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegranttypes.StoreKey], app.AccountKeeper) app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath) // register the staking hooks @@ -347,6 +355,7 @@ func NewSimApp( bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), capability.NewAppModule(appCodec, *app.CapabilityKeeper), crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants), + feegrant.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper), mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper), slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), @@ -379,6 +388,7 @@ func NewSimApp( capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName, slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, crisistypes.ModuleName, ibchost.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, authztypes.ModuleName, ibctransfertypes.ModuleName, + feegranttypes.ModuleName, ) app.mm.RegisterInvariants(&app.CrisisKeeper) @@ -396,6 +406,7 @@ func NewSimApp( auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts), bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), capability.NewAppModule(appCodec, *app.CapabilityKeeper), + feegrant.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper), mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper), staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), @@ -419,8 +430,8 @@ func NewSimApp( app.SetInitChainer(app.InitChainer) app.SetBeginBlocker(app.BeginBlocker) app.SetAnteHandler( - ante.NewAnteHandler( - app.AccountKeeper, app.BankKeeper, ante.DefaultSigVerificationGasConsumer, + feegrantante.NewAnteHandler( + app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, ante.DefaultSigVerificationGasConsumer, encodingConfig.TxConfig.SignModeHandler(), ), ) diff --git a/simapp/params/weights.go b/simapp/params/weights.go index 0ba377b009b1..a7ea85ef7c1d 100644 --- a/simapp/params/weights.go +++ b/simapp/params/weights.go @@ -20,4 +20,8 @@ const ( DefaultWeightCommunitySpendProposal int = 5 DefaultWeightTextProposal int = 5 DefaultWeightParamChangeProposal int = 5 + + // feegrant + DefaultWeightGrantFeeAllowance int = 100 + DefaultWeightRevokeFeeAllowance int = 100 ) diff --git a/x/auth/legacy/legacytx/stdtx_builder.go b/x/auth/legacy/legacytx/stdtx_builder.go index 153c4b2bbbc1..ae0e97a3f34c 100644 --- a/x/auth/legacy/legacytx/stdtx_builder.go +++ b/x/auth/legacy/legacytx/stdtx_builder.go @@ -84,6 +84,9 @@ func (s *StdTxBuilder) SetTimeoutHeight(height uint64) { s.TimeoutHeight = height } +// SetFeeGranter does nothing for stdtx +func (s *StdTxBuilder) SetFeeGranter(_ sdk.AccAddress) {} + // StdTxConfig is a context.TxConfig for StdTx type StdTxConfig struct { Cdc *codec.LegacyAmino diff --git a/x/feegrant/ante/ante.go b/x/feegrant/ante/ante.go new file mode 100644 index 000000000000..483868c23e16 --- /dev/null +++ b/x/feegrant/ante/ante.go @@ -0,0 +1,35 @@ +package ante + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + authante "github.com/cosmos/cosmos-sdk/x/auth/ante" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + "github.com/cosmos/cosmos-sdk/x/auth/signing" + feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + feegranttypes "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +// NewAnteHandler returns an AnteHandler that checks and increments sequence +// numbers, checks signatures & account numbers, and deducts fees from the +// fee_payer or from fee_granter (if valid grant exist). +func NewAnteHandler( + ak authkeeper.AccountKeeper, bankKeeper feegranttypes.BankKeeper, feeGrantKeeper feegrantkeeper.Keeper, + sigGasConsumer authante.SignatureVerificationGasConsumer, signModeHandler signing.SignModeHandler, +) sdk.AnteHandler { + + return sdk.ChainAnteDecorators( + authante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first + authante.NewRejectExtensionOptionsDecorator(), + authante.NewMempoolFeeDecorator(), + authante.NewValidateBasicDecorator(), + authante.TxTimeoutHeightDecorator{}, + authante.NewValidateMemoDecorator(ak), + authante.NewConsumeGasForTxSizeDecorator(ak), + NewDeductGrantedFeeDecorator(ak, bankKeeper, feeGrantKeeper), + authante.NewSetPubKeyDecorator(ak), // SetPubKeyDecorator must be called before all signature verification decorators + authante.NewValidateSigCountDecorator(ak), + authante.NewSigGasConsumeDecorator(ak, sigGasConsumer), + authante.NewSigVerificationDecorator(ak, signModeHandler), + authante.NewIncrementSequenceDecorator(ak), // innermost AnteDecorator + ) +} diff --git a/x/feegrant/ante/fee.go b/x/feegrant/ante/fee.go new file mode 100644 index 000000000000..52cbda7210eb --- /dev/null +++ b/x/feegrant/ante/fee.go @@ -0,0 +1,82 @@ +package ante + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + authante "github.com/cosmos/cosmos-sdk/x/auth/ante" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +// DeductGrantedFeeDecorator deducts fees from fee_payer or fee_granter (if exists a valid fee allowance) of the tx +// If the fee_payer or fee_granter does not have the funds to pay for the fees, return with InsufficientFunds error +// Call next AnteHandler if fees successfully deducted +// CONTRACT: Tx must implement GrantedFeeTx interface to use DeductGrantedFeeDecorator +type DeductGrantedFeeDecorator struct { + ak types.AccountKeeper + k keeper.Keeper + bk types.BankKeeper +} + +func NewDeductGrantedFeeDecorator(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) DeductGrantedFeeDecorator { + return DeductGrantedFeeDecorator{ + ak: ak, + k: k, + bk: bk, + } +} + +// AnteHandle performs a decorated ante-handler responsible for deducting transaction +// fees. Fees will be deducted from the account designated by the FeePayer on a +// transaction by default. However, if the fee payer differs from the transaction +// signer, the handler will check if a fee grant has been authorized. If the +// transaction's signer does not exist, it will be created. +func (d DeductGrantedFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { + feeTx, ok := tx.(sdk.FeeTx) + if !ok { + return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a GrantedFeeTx") + } + + // sanity check from DeductFeeDecorator + if addr := d.ak.GetModuleAddress(authtypes.FeeCollectorName); addr == nil { + panic(fmt.Sprintf("%s module account has not been set", authtypes.FeeCollectorName)) + } + + fee := feeTx.GetFee() + feePayer := feeTx.FeePayer() + feeGranter := feeTx.FeeGranter() + + deductFeesFrom := feePayer + + // ensure the grant is allowed, if we request a different fee payer + if feeGranter != nil && !feeGranter.Equals(feePayer) { + err := d.k.UseGrantedFees(ctx, feeGranter, feePayer, fee) + if err != nil { + return ctx, sdkerrors.Wrapf(err, "%s not allowed to pay fees from %s", feeGranter, feePayer) + } + + deductFeesFrom = feeGranter + } + + // now, either way, we know that we are authorized to deduct the fees from the deductFeesFrom account + deductFeesFromAcc := d.ak.GetAccount(ctx, deductFeesFrom) + if deductFeesFromAcc == nil { + return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "fee payer address: %s does not exist", deductFeesFrom) + } + + // move on if there is no fee to deduct + if fee.IsZero() { + return next(ctx, tx, simulate) + } + + // deduct fee if non-zero + err = authante.DeductFees(d.bk, ctx, deductFeesFromAcc, fee) + if err != nil { + return ctx, err + } + + return next(ctx, tx, simulate) +} diff --git a/x/feegrant/ante/fee_test.go b/x/feegrant/ante/fee_test.go new file mode 100644 index 000000000000..293f448d73f8 --- /dev/null +++ b/x/feegrant/ante/fee_test.go @@ -0,0 +1,287 @@ +package ante_test + +import ( + "math/rand" + "testing" + "time" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/stretchr/testify/suite" + "github.com/tendermint/tendermint/crypto" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/simapp" + "github.com/cosmos/cosmos-sdk/simapp/helpers" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + authante "github.com/cosmos/cosmos-sdk/x/auth/ante" + authsign "github.com/cosmos/cosmos-sdk/x/auth/signing" + "github.com/cosmos/cosmos-sdk/x/auth/tx" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/ante" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +// AnteTestSuite is a test suite to be used with ante handler tests. +type AnteTestSuite struct { + suite.Suite + + app *simapp.SimApp + anteHandler sdk.AnteHandler + ctx sdk.Context + clientCtx client.Context + txBuilder client.TxBuilder +} + +// SetupTest setups a new test, with new app, context, and anteHandler. +func (suite *AnteTestSuite) SetupTest(isCheckTx bool) { + suite.app, suite.ctx = createTestApp(isCheckTx) + suite.ctx = suite.ctx.WithBlockHeight(1) + + // Set up TxConfig. + encodingConfig := simapp.MakeTestEncodingConfig() + // We're using TestMsg encoding in some tests, so register it here. + encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil) + testdata.RegisterInterfaces(encodingConfig.InterfaceRegistry) + + suite.clientCtx = client.Context{}. + WithTxConfig(encodingConfig.TxConfig) + + suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.FeeGrantKeeper, authante.DefaultSigVerificationGasConsumer, encodingConfig.TxConfig.SignModeHandler()) +} + +func (suite *AnteTestSuite) TestDeductFeesNoDelegation() { + suite.SetupTest(true) + // setup + app, ctx := suite.app, suite.ctx + + protoTxCfg := tx.NewTxConfig(codec.NewProtoCodec(app.InterfaceRegistry()), tx.DefaultSignModes) + + // this just tests our handler + dfd := ante.NewDeductGrantedFeeDecorator(app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper) + ourAnteHandler := sdk.ChainAnteDecorators(dfd) + + // this tests the whole stack + anteHandlerStack := suite.anteHandler + + // keys and addresses + priv1, _, addr1 := testdata.KeyTestPubAddr() + priv2, _, addr2 := testdata.KeyTestPubAddr() + priv3, _, addr3 := testdata.KeyTestPubAddr() + priv4, _, addr4 := testdata.KeyTestPubAddr() + priv5, _, addr5 := testdata.KeyTestPubAddr() + + // Set addr1 with insufficient funds + acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) + app.AccountKeeper.SetAccount(ctx, acc1) + app.BankKeeper.SetBalances(ctx, addr1, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(10))}) + + // Set addr2 with more funds + acc2 := app.AccountKeeper.NewAccountWithAddress(ctx, addr2) + app.AccountKeeper.SetAccount(ctx, acc2) + app.BankKeeper.SetBalances(ctx, addr2, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(99999))}) + + // grant fee allowance from `addr2` to `addr3` (plenty to pay) + err := app.FeeGrantKeeper.GrantFeeAllowance(ctx, addr2, addr3, &types.BasicFeeAllowance{ + SpendLimit: sdk.NewCoins(sdk.NewInt64Coin("atom", 500)), + }) + suite.Require().NoError(err) + + // grant low fee allowance (20atom), to check the tx requesting more than allowed. + err = app.FeeGrantKeeper.GrantFeeAllowance(ctx, addr2, addr4, &types.BasicFeeAllowance{ + SpendLimit: sdk.NewCoins(sdk.NewInt64Coin("atom", 20)), + }) + suite.Require().NoError(err) + + cases := map[string]struct { + signerKey cryptotypes.PrivKey + signer sdk.AccAddress + feeAccount sdk.AccAddress + feeAccountKey cryptotypes.PrivKey + handler sdk.AnteHandler + fee int64 + valid bool + }{ + "paying with low funds (only ours)": { + signerKey: priv1, + signer: addr1, + fee: 50, + handler: ourAnteHandler, + valid: false, + }, + "paying with good funds (only ours)": { + signerKey: priv2, + signer: addr2, + fee: 50, + handler: ourAnteHandler, + valid: true, + }, + "paying with no account (only ours)": { + signerKey: priv3, + signer: addr3, + fee: 1, + handler: ourAnteHandler, + valid: false, + }, + "no fee with real account (only ours)": { + signerKey: priv1, + signer: addr1, + fee: 0, + handler: ourAnteHandler, + valid: true, + }, + "no fee with no account (only ours)": { + signerKey: priv5, + signer: addr5, + fee: 0, + handler: ourAnteHandler, + valid: false, + }, + "valid fee grant without account (only ours)": { + signerKey: priv3, + signer: addr3, + feeAccount: addr2, + fee: 50, + handler: ourAnteHandler, + valid: true, + }, + "no fee grant (only ours)": { + signerKey: priv3, + signer: addr3, + feeAccount: addr1, + fee: 2, + handler: ourAnteHandler, + valid: false, + }, + "allowance smaller than requested fee (only ours)": { + signerKey: priv4, + signer: addr4, + feeAccount: addr2, + fee: 50, + handler: ourAnteHandler, + valid: false, + }, + "granter cannot cover allowed fee grant (only ours)": { + signerKey: priv4, + signer: addr4, + feeAccount: addr1, + fee: 50, + handler: ourAnteHandler, + valid: false, + }, + } + + for name, stc := range cases { + tc := stc // to make scopelint happy + suite.T().Run(name, func(t *testing.T) { + fee := sdk.NewCoins(sdk.NewInt64Coin("atom", tc.fee)) + msgs := []sdk.Msg{testdata.NewTestMsg(tc.signer)} + + acc := app.AccountKeeper.GetAccount(ctx, tc.signer) + privs, accNums, seqs := []cryptotypes.PrivKey{tc.signerKey}, []uint64{0}, []uint64{0} + if acc != nil { + accNums, seqs = []uint64{acc.GetAccountNumber()}, []uint64{acc.GetSequence()} + } + + tx, err := genTxWithFeeGranter(protoTxCfg, msgs, fee, helpers.DefaultGenTxGas, ctx.ChainID(), accNums, seqs, tc.feeAccount, privs...) + suite.Require().NoError(err) + _, err = ourAnteHandler(ctx, tx, false) + if tc.valid { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + } + + _, err = anteHandlerStack(ctx, tx, false) + if tc.valid { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + } + }) + } +} + +// returns context and app with params set on account keeper +func createTestApp(isCheckTx bool) (*simapp.SimApp, sdk.Context) { + app := simapp.Setup(isCheckTx) + ctx := app.BaseApp.NewContext(isCheckTx, tmproto.Header{}) + app.AccountKeeper.SetParams(ctx, authtypes.DefaultParams()) + + return app, ctx +} + +// don't consume any gas +func SigGasNoConsumer(meter sdk.GasMeter, sig []byte, pubkey crypto.PubKey, params authtypes.Params) error { + return nil +} + +func genTxWithFeeGranter(gen client.TxConfig, msgs []sdk.Msg, feeAmt sdk.Coins, gas uint64, chainID string, accNums, + accSeqs []uint64, feeGranter sdk.AccAddress, priv ...cryptotypes.PrivKey) (sdk.Tx, error) { + sigs := make([]signing.SignatureV2, len(priv)) + + // create a random length memo + r := rand.New(rand.NewSource(time.Now().UnixNano())) + + memo := simulation.RandStringOfLength(r, simulation.RandIntBetween(r, 0, 100)) + + signMode := gen.SignModeHandler().DefaultMode() + + // 1st round: set SignatureV2 with empty signatures, to set correct + // signer infos. + for i, p := range priv { + sigs[i] = signing.SignatureV2{ + PubKey: p.PubKey(), + Data: &signing.SingleSignatureData{ + SignMode: signMode, + }, + Sequence: accSeqs[i], + } + } + + tx := gen.NewTxBuilder() + err := tx.SetMsgs(msgs...) + if err != nil { + return nil, err + } + err = tx.SetSignatures(sigs...) + if err != nil { + return nil, err + } + tx.SetMemo(memo) + tx.SetFeeAmount(feeAmt) + tx.SetGasLimit(gas) + tx.SetFeeGranter(feeGranter) + + // 2nd round: once all signer infos are set, every signer can sign. + for i, p := range priv { + signerData := authsign.SignerData{ + ChainID: chainID, + AccountNumber: accNums[i], + Sequence: accSeqs[i], + } + signBytes, err := gen.SignModeHandler().GetSignBytes(signMode, signerData, tx.GetTx()) + if err != nil { + panic(err) + } + sig, err := p.Sign(signBytes) + if err != nil { + panic(err) + } + sigs[i].Data.(*signing.SingleSignatureData).Signature = sig + err = tx.SetSignatures(sigs...) + if err != nil { + panic(err) + } + } + + return tx.GetTx(), nil +} + +func TestAnteTestSuite(t *testing.T) { + suite.Run(t, new(AnteTestSuite)) +} diff --git a/x/feegrant/client/cli/cli_test.go b/x/feegrant/client/cli/cli_test.go new file mode 100644 index 000000000000..224e7282a80a --- /dev/null +++ b/x/feegrant/client/cli/cli_test.go @@ -0,0 +1,621 @@ +// +build norace + +package cli_test + +import ( + "fmt" + "testing" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + "github.com/cosmos/cosmos-sdk/testutil/network" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/client/cli" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + govtestutil "github.com/cosmos/cosmos-sdk/x/gov/client/testutil" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/gogo/protobuf/proto" + "github.com/stretchr/testify/suite" + tmcli "github.com/tendermint/tendermint/libs/cli" +) + +type IntegrationTestSuite struct { + suite.Suite + + cfg network.Config + network *network.Network + addedGranter sdk.AccAddress + addedGrantee sdk.AccAddress + addedGrant types.FeeAllowanceGrant +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + if testing.Short() { + s.T().Skip("skipping test in unit-tests mode.") + } + + cfg := network.DefaultConfig() + cfg.NumValidators = 2 + + s.cfg = cfg + s.network = network.New(s.T(), cfg) + + _, err := s.network.WaitForHeight(1) + s.Require().NoError(err) + + val := s.network.Validators[0] + granter := val.Address + grantee := s.network.Validators[1].Address + + clientCtx := val.ClientCtx + commonFlags := []string{ + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + fee := sdk.NewCoin("stake", sdk.NewInt(100)) + duration := 365 * 24 * 60 * 60 + + args := append( + []string{ + granter.String(), + grantee.String(), + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, fee.String()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + fmt.Sprintf("--%s=%v", cli.FlagExpiration, duration), + }, + commonFlags..., + ) + + cmd := cli.NewCmdFeeGrant() + + _, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args) + s.Require().NoError(err) + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) + + s.addedGranter = granter + s.addedGrantee = grantee + + grant, err := types.NewFeeAllowanceGrant(granter, grantee, &types.BasicFeeAllowance{ + SpendLimit: sdk.NewCoins(fee), + }) + s.Require().NoError(err) + + s.addedGrant = grant +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +func (s *IntegrationTestSuite) TestCmdGetFeeGrant() { + val := s.network.Validators[0] + granter := val.Address + grantee := s.addedGrantee + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErrMsg string + expectErr bool + respType *types.FeeAllowanceGrant + resp *types.FeeAllowanceGrant + }{ + { + "wrong granter", + []string{ + "wrong_granter", + grantee.String(), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "decoding bech32 failed", + true, nil, nil, + }, + { + "wrong grantee", + []string{ + granter.String(), + "wrong_grantee", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "decoding bech32 failed", + true, nil, nil, + }, + { + "non existed grant", + []string{ + "cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl", + grantee.String(), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "no fee allowance found", + true, nil, nil, + }, + { + "valid req", + []string{ + granter.String(), + grantee.String(), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "", + false, + &types.FeeAllowanceGrant{}, + &s.addedGrant, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryFeeGrant() + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.expectErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.expectErrMsg) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + s.Require().Equal(tc.respType.Grantee, tc.respType.Grantee) + s.Require().Equal(tc.respType.Granter, tc.respType.Granter) + s.Require().Equal( + tc.respType.GetFeeGrant().(*types.BasicFeeAllowance).SpendLimit, + tc.resp.GetFeeGrant().(*types.BasicFeeAllowance).SpendLimit, + ) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdGetFeeGrants() { + val := s.network.Validators[0] + grantee := s.addedGrantee + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErr bool + resp *types.QueryFeeAllowancesResponse + expectLength int + }{ + { + "wrong grantee", + []string{ + "wrong_grantee", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + true, nil, 0, + }, + { + "non existed grantee", + []string{ + "cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + false, &types.QueryFeeAllowancesResponse{}, 0, + }, + { + "valid req", + []string{ + grantee.String(), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + false, &types.QueryFeeAllowancesResponse{}, 1, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryFeeGrants() + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.resp), out.String()) + s.Require().Len(tc.resp.FeeAllowances, tc.expectLength) + } + }) + } +} + +func (s *IntegrationTestSuite) TestNewCmdFeeGrant() { + val := s.network.Validators[0] + granter := val.Address + alreadyExistedGrantee := s.addedGrantee + clientCtx := val.ClientCtx + + commonFlags := []string{ + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + testCases := []struct { + name string + args []string + expectErr bool + respType proto.Message + expectedCode uint32 + }{ + { + "wrong granter address", + append( + []string{ + "wrong_granter", + "cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + true, nil, 0, + }, + { + "wrong grantee address", + append( + []string{ + granter.String(), + "wrong_grantee", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + true, nil, 0, + }, + { + "valid basic fee grant", + append( + []string{ + granter.String(), + "cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 0, + }, + { + "valid basic fee grant without spend limit", + append( + []string{ + granter.String(), + "cosmos17h5lzptx3ghvsuhk7wx4c4hnl7rsswxjer97em", + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 0, + }, + { + "valid basic fee grant without expiration", + append( + []string{ + granter.String(), + "cosmos16dlc38dcqt0uralyd8hksxyrny6kaeqfjvjwp5", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 0, + }, + { + "valid basic fee grant without spend-limit and expiration", + append( + []string{ + granter.String(), + "cosmos1ku40qup9vwag4wtf8cls9mkszxfthaklxkp3c8", + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 0, + }, + { + "try to add existed grant", + append( + []string{ + granter.String(), + alreadyExistedGrantee.String(), + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 18, + }, + { + "invalid number of args(periodic fee grant)", + append( + []string{ + granter.String(), + "cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, 10*60*60), + }, + commonFlags..., + ), + true, nil, 0, + }, + { + "period mentioned and period limit omitted, invalid periodic grant", + append( + []string{ + granter.String(), + "cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%d", cli.FlagPeriod, 10*60*60), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, 60*60), + }, + commonFlags..., + ), + true, nil, 0, + }, + { + "period cannot be greater than the actual expiration(periodic fee grant)", + append( + []string{ + granter.String(), + "cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%d", cli.FlagPeriod, 10*60*60), + fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, 60*60), + }, + commonFlags..., + ), + true, nil, 0, + }, + { + "valid periodic fee grant", + append( + []string{ + granter.String(), + "cosmos1w55kgcf3ltaqdy4ww49nge3klxmrdavrr6frmp", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%d", cli.FlagPeriod, 60*60), + fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, 10*60*60), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 0, + }, + { + "valid periodic fee grant without spend-limit", + append( + []string{ + granter.String(), + "cosmos1vevyks8pthkscvgazc97qyfjt40m6g9xe85ry8", + fmt.Sprintf("--%s=%d", cli.FlagPeriod, 60*60), + fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, 10*60*60), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 0, + }, + { + "valid periodic fee grant without expiration", + append( + []string{ + granter.String(), + "cosmos14cm33pvnrv2497tyt8sp9yavhmw83nwej3m0e8", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%d", cli.FlagPeriod, 60*60), + fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 0, + }, + { + "valid periodic fee grant without spend-limit and expiration", + append( + []string{ + granter.String(), + "cosmos12nyk4pcf4arshznkpz882e4l4ts0lt0ap8ce54", + fmt.Sprintf("--%s=%d", cli.FlagPeriod, 60*60), + fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.NewCmdFeeGrant() + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestNewCmdRevokeFeegrant() { + val := s.network.Validators[0] + granter := s.addedGranter + grantee := s.addedGrantee + clientCtx := val.ClientCtx + + commonFlags := []string{ + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + testCases := []struct { + name string + args []string + expectErr bool + respType proto.Message + expectedCode uint32 + }{ + { + "invalid grantee", + append( + []string{ + "wrong_granter", + grantee.String(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + true, + nil, + 0, + }, + { + "invalid grantee", + append( + []string{ + granter.String(), + "wrong_grantee", + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + true, + nil, + 0, + }, + { + "Non existed grant", + append( + []string{ + granter.String(), + "cosmos1aeuqja06474dfrj7uqsvukm6rael982kk89mqr", + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, + &sdk.TxResponse{}, + 4, + }, + { + "Valid revoke", + append( + []string{ + granter.String(), + grantee.String(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, + &sdk.TxResponse{}, + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.NewCmdRevokeFeegrant() + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestTxWithFeeGrant() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + granter := val.Address + + // creating an account manually (This account won't be exist in state) + info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + s.Require().NoError(err) + grantee := sdk.AccAddress(info.GetPubKey().Address()) + + commonFlags := []string{ + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + fee := sdk.NewCoin("stake", sdk.NewInt(100)) + duration := 365 * 24 * 60 * 60 + + args := append( + []string{ + granter.String(), + grantee.String(), + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, fee.String()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + fmt.Sprintf("--%s=%v", cli.FlagExpiration, duration), + }, + commonFlags..., + ) + + cmd := cli.NewCmdFeeGrant() + + _, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args) + s.Require().NoError(err) + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) + + // granted fee allowance for an account which is not in state and creating + // any tx with it by using --fee-account shouldn't fail + out, err := govtestutil.MsgSubmitProposal(val.ClientCtx, grantee.String(), + "Text Proposal", "No desc", govtypes.ProposalTypeText, + fmt.Sprintf("--%s=%s", flags.FlagFeeAccount, granter.String()), + ) + + s.Require().NoError(err) + var resp sdk.TxResponse + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &resp), out.String()) + s.Require().Equal(uint32(0), resp.Code) +} + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/feegrant/client/cli/query.go b/x/feegrant/client/cli/query.go new file mode 100644 index 000000000000..c3a488ab5536 --- /dev/null +++ b/x/feegrant/client/cli/query.go @@ -0,0 +1,129 @@ +package cli + +import ( + "fmt" + "strings" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/spf13/cobra" +) + +// GetQueryCmd returns the cli query commands for this module +func GetQueryCmd() *cobra.Command { + feegrantQueryCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Querying commands for the feegrant module", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + feegrantQueryCmd.AddCommand( + GetCmdQueryFeeGrant(), + GetCmdQueryFeeGrants(), + ) + + return feegrantQueryCmd +} + +// GetCmdQueryFeeGrant returns cmd to query for a grant between granter and grantee. +func GetCmdQueryFeeGrant() *cobra.Command { + cmd := &cobra.Command{ + Use: "grant [granter] [grantee]", + Args: cobra.ExactArgs(2), + Short: "Query details of a single grant", + Long: strings.TrimSpace( + fmt.Sprintf(`Query details for a grant. +You can find the fee-grant of a granter and grantee. + +Example: +$ %s query feegrant grant [granter] [grantee] +`, version.AppName), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd) + queryClient := types.NewQueryClient(clientCtx) + + granterAddr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + granteeAddr, err := sdk.AccAddressFromBech32(args[1]) + if err != nil { + return err + } + + res, err := queryClient.FeeAllowance( + cmd.Context(), + &types.QueryFeeAllowanceRequest{ + Granter: granterAddr.String(), + Grantee: granteeAddr.String(), + }, + ) + + if err != nil { + return err + } + + return clientCtx.PrintProto(res.FeeAllowance) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// GetCmdQueryFeeGrants returns cmd to query for all grants for a grantee. +func GetCmdQueryFeeGrants() *cobra.Command { + cmd := &cobra.Command{ + Use: "grants [grantee]", + Args: cobra.ExactArgs(1), + Short: "Query all grants of a grantee", + Long: strings.TrimSpace( + fmt.Sprintf(`Queries all the grants for a grantee address. + +Example: +$ %s query feegrant grants [grantee] +`, version.AppName), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd) + queryClient := types.NewQueryClient(clientCtx) + + granteeAddr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + res, err := queryClient.FeeAllowances( + cmd.Context(), + &types.QueryFeeAllowancesRequest{ + Grantee: granteeAddr.String(), + Pagination: pageReq, + }, + ) + + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "grants") + + return cmd +} diff --git a/x/feegrant/client/cli/tx.go b/x/feegrant/client/cli/tx.go new file mode 100644 index 000000000000..a28ddb976cc1 --- /dev/null +++ b/x/feegrant/client/cli/tx.go @@ -0,0 +1,211 @@ +package cli + +import ( + "fmt" + "strings" + "time" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + "github.com/cosmos/cosmos-sdk/version" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +// flag for feegrant module +const ( + FlagExpiration = "expiration" + FlagPeriod = "period" + FlagPeriodLimit = "period-limit" + FlagSpendLimit = "spend-limit" +) + +// GetTxCmd returns the transaction commands for this module +func GetTxCmd() *cobra.Command { + feegrantTxCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Feegrant transactions subcommands", + Long: "Grant and revoke fee allowance for a grantee by a granter", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + feegrantTxCmd.AddCommand( + NewCmdFeeGrant(), + NewCmdRevokeFeegrant(), + ) + + return feegrantTxCmd +} + +// NewCmdFeeGrant returns a CLI command handler for creating a MsgGrantFeeAllowance transaction. +func NewCmdFeeGrant() *cobra.Command { + cmd := &cobra.Command{ + Use: "grant [granter] [grantee]", + Short: "Grant Fee allowance to an address", + Long: strings.TrimSpace( + fmt.Sprintf( + `Grant authorization to pay fees from your address. Note, the'--from' flag is + ignored as it is implied from [granter]. + +Examples: +%s tx %s grant cosmos1skjw... cosmos1skjw... --spend-limit 100stake --expiration 36000 or +%s tx %s grant cosmos1skjw... cosmos1skjw... --spend-limit 100stake --period 3600 --period-limit 10stake --expiration 36000 + `, version.AppName, types.ModuleName, version.AppName, types.ModuleName, + ), + ), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + _, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + cmd.Flags().Set(flags.FlagFrom, args[0]) + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + grantee, err := sdk.AccAddressFromBech32(args[1]) + if err != nil { + return err + } + + granter := clientCtx.GetFromAddress() + sl, err := cmd.Flags().GetString(FlagSpendLimit) + if err != nil { + return err + } + + // if `FlagSpendLimit` isn't set, limit will be nil + limit, err := sdk.ParseCoinsNormalized(sl) + if err != nil { + return err + } + + exp, err := cmd.Flags().GetInt64(FlagExpiration) + if err != nil { + return err + } + + basic := types.BasicFeeAllowance{ + SpendLimit: limit, + } + + if exp != 0 { + expDuration := time.Duration(exp) * time.Second + basic.Expiration = types.ExpiresAtTime(time.Now().Add(expDuration)) + } + + var grant types.FeeAllowanceI + grant = &basic + + periodClock, err := cmd.Flags().GetInt64(FlagPeriod) + if err != nil { + return err + } + + periodLimitVal, err := cmd.Flags().GetString(FlagPeriodLimit) + if err != nil { + return err + } + + // Check any of period or periodLimit flags set, If set consider it as periodic fee allowance. + if periodClock > 0 || periodLimitVal != "" { + periodLimit, err := sdk.ParseCoinsNormalized(periodLimitVal) + if err != nil { + return err + } + + if periodClock > 0 && periodLimit != nil { + if exp > 0 && periodClock > exp { + return fmt.Errorf("period(%d) cannot be greater than the expiration(%d)", periodClock, exp) + } + + periodic := types.PeriodicFeeAllowance{ + Basic: basic, + Period: types.ClockDuration(time.Duration(periodClock) * time.Second), + PeriodReset: types.ExpiresAtTime(time.Now().Add(time.Duration(periodClock) * time.Second)), + PeriodSpendLimit: periodLimit, + PeriodCanSpend: periodLimit, + } + + grant = &periodic + + } else { + return fmt.Errorf("invalid number of args %d", len(args)) + } + } + + msg, err := types.NewMsgGrantFeeAllowance(grant, granter, grantee) + if err != nil { + return err + } + + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + feeGrantMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = feeGrantMsgClient.GrantFeeAllowance(cmd.Context(), msg) + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) + }, + } + + flags.AddTxFlagsToCmd(cmd) + cmd.Flags().Int64(FlagExpiration, 0, "The second unit of time duration which the grant is active for the user") + cmd.Flags().String(FlagSpendLimit, "", "Spend limit specifies the max limit can be used, if not mentioned there is no limit") + cmd.Flags().Int64(FlagPeriod, 0, "period specifies the time duration in which period_spend_limit coins can be spent before that allowance is reset") + cmd.Flags().String(FlagPeriodLimit, "", "// period limit specifies the maximum number of coins that can be spent in the period") + + return cmd +} + +// NewCmdRevokeFeegrant returns a CLI command handler for creating a MsgRevokeFeeAllowance transaction. +func NewCmdRevokeFeegrant() *cobra.Command { + cmd := &cobra.Command{ + Use: "revoke [granter_address] [grantee_address]", + Short: "revoke fee-grant", + Long: strings.TrimSpace( + fmt.Sprintf(`revoke fee grant from a granter to a grantee. Note, the'--from' flag is + ignored as it is implied from [granter_address]. + +Example: + $ %s tx %s revoke cosmos1skj.. cosmos1skj.. + `, version.AppName, types.ModuleName), + ), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + cmd.Flags().Set(flags.FlagFrom, args[0]) + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + grantee, err := sdk.AccAddressFromBech32(args[1]) + if err != nil { + return err + } + + msg := types.NewMsgRevokeFeeAllowance(clientCtx.GetFromAddress(), grantee) + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + feeGrantMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = feeGrantMsgClient.RevokeFeeAllowance(cmd.Context(), &msg) + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) + }, + } + + flags.AddTxFlagsToCmd(cmd) + return cmd +} diff --git a/x/feegrant/client/rest/grpc_query_test.go b/x/feegrant/client/rest/grpc_query_test.go new file mode 100644 index 000000000000..10d77a1e4c1f --- /dev/null +++ b/x/feegrant/client/rest/grpc_query_test.go @@ -0,0 +1,209 @@ +package rest_test + +import ( + "fmt" + "testing" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + "github.com/cosmos/cosmos-sdk/testutil/network" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/rest" + banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" + "github.com/cosmos/cosmos-sdk/x/feegrant/client/cli" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/stretchr/testify/suite" +) + +type IntegrationTestSuite struct { + suite.Suite + cfg network.Config + network *network.Network + grantee sdk.AccAddress +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + cfg := network.DefaultConfig() + + cfg.NumValidators = 1 + s.cfg = cfg + s.network = network.New(s.T(), cfg) + + val := s.network.Validators[0] + // Create new account in the keyring. + info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + s.Require().NoError(err) + newAddr := sdk.AccAddress(info.GetPubKey().Address()) + + // Send some funds to the new account. + _, err = banktestutil.MsgSendExec( + val.ClientCtx, + val.Address, + newAddr, + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + ) + s.Require().NoError(err) + + s.grantee = newAddr + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +func (s *IntegrationTestSuite) TestQueryFeeAllowance() { + val := s.network.Validators[0] + baseURL := val.APIAddress + testCases := []struct { + name string + url string + expectErr bool + errorMsg string + preRun func() + postRun func(_ types.QueryFeeAllowanceResponse) + }{ + { + "fail: invalid granter", + fmt.Sprintf("%s/cosmos/feegrant/v1beta1/fee_allowance/%s/%s", baseURL, "invalid_granter", s.grantee.String()), + true, + "decoding bech32 failed: invalid index of 1: invalid request", + func() {}, + func(types.QueryFeeAllowanceResponse) {}, + }, + { + "fail: invalid grantee", + fmt.Sprintf("%s/cosmos/feegrant/v1beta1/fee_allowance/%s/%s", baseURL, val.Address.String(), "invalid_grantee"), + true, + "decoding bech32 failed: invalid index of 1: invalid request", + func() {}, + func(types.QueryFeeAllowanceResponse) {}, + }, + { + "fail: no grants", + fmt.Sprintf("%s/cosmos/feegrant/v1beta1/fee_allowance/%s/%s", baseURL, val.Address.String(), s.grantee.String()), + true, + "no fee allowance found", + func() {}, + func(types.QueryFeeAllowanceResponse) {}, + }, + { + "valid query: expect single grant", + fmt.Sprintf("%s/cosmos/feegrant/v1beta1/fee_allowance/%s/%s", baseURL, val.Address.String(), s.grantee.String()), + false, + "", + func() { + execFeeAllowance(val, s) + }, + func(allowance types.QueryFeeAllowanceResponse) { + s.Require().Equal(allowance.FeeAllowance.Granter, val.Address.String()) + s.Require().Equal(allowance.FeeAllowance.Grantee, s.grantee.String()) + }, + }, + } + for _, tc := range testCases { + s.Run(tc.name, func() { + tc.preRun() + resp, _ := rest.GetRequest(tc.url) + if tc.expectErr { + s.Require().Contains(string(resp), tc.errorMsg) + } else { + var allowance types.QueryFeeAllowanceResponse + err := val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, &allowance) + s.Require().NoError(err) + tc.postRun(allowance) + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryGranteeAllowances() { + val := s.network.Validators[0] + baseURL := val.APIAddress + testCases := []struct { + name string + url string + expectErr bool + errorMsg string + preRun func() + postRun func(_ types.QueryFeeAllowancesResponse) + }{ + { + "fail: invalid grantee", + fmt.Sprintf("%s/cosmos/feegrant/v1beta1/fee_allowances/%s", baseURL, "invalid_grantee"), + true, + "decoding bech32 failed: invalid index of 1: invalid request", + func() {}, + func(types.QueryFeeAllowancesResponse) {}, + }, + { + "success: no grants", + fmt.Sprintf("%s/cosmos/feegrant/v1beta1/fee_allowances/%s?pagination.offset=1", baseURL, s.grantee.String()), + false, + "", + func() {}, + func(allowances types.QueryFeeAllowancesResponse) { + s.Require().Equal(len(allowances.FeeAllowances), 0) + }, + }, + { + "valid query: expect single grant", + fmt.Sprintf("%s/cosmos/feegrant/v1beta1/fee_allowances/%s", baseURL, s.grantee.String()), + false, + "", + func() { + execFeeAllowance(val, s) + }, + func(allowances types.QueryFeeAllowancesResponse) { + s.Require().Equal(len(allowances.FeeAllowances), 1) + s.Require().Equal(allowances.FeeAllowances[0].Granter, val.Address.String()) + s.Require().Equal(allowances.FeeAllowances[0].Grantee, s.grantee.String()) + }, + }, + } + for _, tc := range testCases { + s.Run(tc.name, func() { + tc.preRun() + resp, _ := rest.GetRequest(tc.url) + if tc.expectErr { + s.Require().Contains(string(resp), tc.errorMsg) + } else { + var allowance types.QueryFeeAllowancesResponse + err := val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, &allowance) + s.Require().NoError(err) + tc.postRun(allowance) + } + }) + } +} + +func execFeeAllowance(val *network.Validator, s *IntegrationTestSuite) { + fee := sdk.NewCoin("steak", sdk.NewInt(100)) + duration := 365 * 24 * 60 * 60 + args := []string{ + val.Address.String(), + s.grantee.String(), + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, fee.String()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%v", cli.FlagExpiration, duration), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + cmd := cli.NewCmdFeeGrant() + _, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cmd, args) + s.Require().NoError(err) +} + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/feegrant/doc.go b/x/feegrant/doc.go new file mode 100644 index 000000000000..4f190e3140c7 --- /dev/null +++ b/x/feegrant/doc.go @@ -0,0 +1,29 @@ +/* +Package feegrant provides functionality for authorizing the payment of transaction +fees from one account (key) to another account (key). + +Effectively, this allows for a user to pay fees using the balance of an account +different from their own. Example use cases would be allowing a key on a device to +pay for fees using a master wallet, or a third party service allowing users to +pay for transactions without ever really holding their own tokens. This package +provides ways for specifying fee allowances such that authorizing fee payment to +another account can be done with clear and safe restrictions. + +A user would authorize granting fee payment to another user using +MsgDelegateFeeAllowance and revoke that delegation using MsgRevokeFeeAllowance. +In both cases, Granter is the one who is authorizing fee payment and Grantee is +the one who is receiving the fee payment authorization. So grantee would correspond +to the one who is signing a transaction and the granter would be the address that +pays the fees. + +The fee allowance that a grantee receives is specified by an implementation of +the FeeAllowance interface. Two FeeAllowance implementations are provided in +this package: BasicFeeAllowance and PeriodicFeeAllowance. + +In order to integrate this into an application, we must use the DeductGrantedFeeDecorator +ante handler from this package instead of the default DeductFeeDecorator from x/auth. + +To allow handling txs from empty accounts (with fees paid from an existing account), +we have to re-order the decorators as well. +*/ +package feegrant diff --git a/x/feegrant/genesis.go b/x/feegrant/genesis.go new file mode 100644 index 000000000000..f65cfdb57825 --- /dev/null +++ b/x/feegrant/genesis.go @@ -0,0 +1,61 @@ +package feegrant + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +// GenesisState contains a set of fee allowances, persisted from the store +type GenesisState []types.FeeAllowanceGrant + +// ValidateBasic ensures all grants in the genesis state are valid +func (g GenesisState) ValidateBasic() error { + for _, f := range g { + err := f.GetFeeGrant().ValidateBasic() + if err != nil { + return err + } + } + return nil +} + +// InitGenesis will initialize the keeper from a *previously validated* GenesisState +func InitGenesis(ctx sdk.Context, k keeper.Keeper, data *types.GenesisState) { + for _, f := range data.FeeAllowances { + granter, err := sdk.AccAddressFromBech32(f.Granter) + if err != nil { + panic(err) + } + grantee, err := sdk.AccAddressFromBech32(f.Grantee) + if err != nil { + panic(err) + } + + err = k.GrantFeeAllowance(ctx, granter, grantee, f.GetFeeGrant()) + if err != nil { + panic(err) + } + } +} + +// ExportGenesis will dump the contents of the keeper into a serializable GenesisState +// +// All expiration heights will be thrown off if we dump state and start at a new +// chain at height 0. Thus, we allow the Allowances to "prepare themselves" +// for export, like if they have expiry at 5000 and current is 4000, they export with +// expiry of 1000. Every FeeAllowance has a method `PrepareForExport` that allows +// them to perform any changes needed prior to export. +func ExportGenesis(ctx sdk.Context, k keeper.Keeper) (*types.GenesisState, error) { + time, height := ctx.BlockTime(), ctx.BlockHeight() + var grants []types.FeeAllowanceGrant + + err := k.IterateAllFeeAllowances(ctx, func(grant types.FeeAllowanceGrant) bool { + grants = append(grants, grant.PrepareForExport(time, height)) + return false + }) + + return &types.GenesisState{ + FeeAllowances: grants, + }, err +} diff --git a/x/feegrant/genesis_test.go b/x/feegrant/genesis_test.go new file mode 100644 index 000000000000..d086daac077f --- /dev/null +++ b/x/feegrant/genesis_test.go @@ -0,0 +1,56 @@ +package feegrant_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" + feegrant "github.com/cosmos/cosmos-sdk/x/feegrant" + "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/stretchr/testify/suite" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" +) + +type GenesisTestSuite struct { + suite.Suite + ctx sdk.Context + keeper keeper.Keeper +} + +func (suite *GenesisTestSuite) SetupTest() { + checkTx := false + app := simapp.Setup(checkTx) + suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1}) + suite.keeper = app.FeeGrantKeeper +} + +var ( + granteePub = secp256k1.GenPrivKey().PubKey() + granterPub = secp256k1.GenPrivKey().PubKey() + granteeAddr = sdk.AccAddress(granteePub.Address()) + granterAddr = sdk.AccAddress(granterPub.Address()) +) + +func (suite *GenesisTestSuite) TestImportExportGenesis() { + coins := sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(1_000))) + now := suite.ctx.BlockHeader().Time + + allowance := &types.BasicFeeAllowance{SpendLimit: coins, Expiration: types.ExpiresAtTime(now.AddDate(1, 0, 0))} + err := suite.keeper.GrantFeeAllowance(suite.ctx, granterAddr, granteeAddr, allowance) + suite.Require().NoError(err) + + genesis, err := feegrant.ExportGenesis(suite.ctx, suite.keeper) + suite.Require().NoError(err) + // Clear keeper + suite.keeper.RevokeFeeAllowance(suite.ctx, granterAddr, granteeAddr) + feegrant.InitGenesis(suite.ctx, suite.keeper, genesis) + newGenesis, err := feegrant.ExportGenesis(suite.ctx, suite.keeper) + suite.Require().NoError(err) + suite.Require().Equal(genesis, newGenesis) +} + +func TestGenesisTestSuite(t *testing.T) { + suite.Run(t, new(GenesisTestSuite)) +} diff --git a/x/feegrant/keeper/grpc_query.go b/x/feegrant/keeper/grpc_query.go new file mode 100644 index 000000000000..0fce084f90ba --- /dev/null +++ b/x/feegrant/keeper/grpc_query.go @@ -0,0 +1,94 @@ +package keeper + +import ( + "context" + + "github.com/gogo/protobuf/proto" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +var _ types.QueryServer = Keeper{} + +// FeeAllowance returns fee granted to the grantee by the granter. +func (q Keeper) FeeAllowance(c context.Context, req *types.QueryFeeAllowanceRequest) (*types.QueryFeeAllowanceResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + granterAddr, err := sdk.AccAddressFromBech32(req.Granter) + if err != nil { + return nil, err + } + + granteeAddr, err := sdk.AccAddressFromBech32(req.Grantee) + if err != nil { + return nil, err + } + + ctx := sdk.UnwrapSDKContext(c) + + feeAllowance := q.GetFeeAllowance(ctx, granterAddr, granteeAddr) + if feeAllowance == nil { + return nil, status.Errorf(codes.NotFound, "no fee allowance found") + } + + msg, ok := feeAllowance.(proto.Message) + if !ok { + return nil, status.Errorf(codes.Internal, "can't proto marshal %T", msg) + } + + feeAllowanceAny, err := codectypes.NewAnyWithValue(msg) + if err != nil { + return nil, status.Errorf(codes.Internal, err.Error()) + } + + return &types.QueryFeeAllowanceResponse{ + FeeAllowance: &types.FeeAllowanceGrant{ + Granter: granterAddr.String(), + Grantee: granteeAddr.String(), + Allowance: feeAllowanceAny, + }, + }, nil +} + +func (q Keeper) FeeAllowances(c context.Context, req *types.QueryFeeAllowancesRequest) (*types.QueryFeeAllowancesResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + granteeAddr, err := sdk.AccAddressFromBech32(req.Grantee) + if err != nil { + return nil, err + } + + ctx := sdk.UnwrapSDKContext(c) + + var grants []*types.FeeAllowanceGrant + + store := ctx.KVStore(q.storeKey) + grantsStore := prefix.NewStore(store, types.FeeAllowancePrefixByGrantee(granteeAddr)) + + pageRes, err := query.Paginate(grantsStore, req.Pagination, func(key []byte, value []byte) error { + var grant types.FeeAllowanceGrant + + if err := q.cdc.UnmarshalBinaryBare(value, &grant); err != nil { + return err + } + + grants = append(grants, &grant) + return nil + }) + + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.QueryFeeAllowancesResponse{FeeAllowances: grants, Pagination: pageRes}, nil +} diff --git a/x/feegrant/keeper/keeper.go b/x/feegrant/keeper/keeper.go new file mode 100644 index 000000000000..e6606bf0ca55 --- /dev/null +++ b/x/feegrant/keeper/keeper.go @@ -0,0 +1,190 @@ +package keeper + +import ( + "fmt" + + "github.com/tendermint/tendermint/libs/log" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +// Keeper manages state of all fee grants, as well as calculating approval. +// It must have a codec with all available allowances registered. +type Keeper struct { + cdc codec.BinaryMarshaler + storeKey sdk.StoreKey + authKeeper types.AccountKeeper +} + +// NewKeeper creates a fee grant Keeper +func NewKeeper(cdc codec.BinaryMarshaler, storeKey sdk.StoreKey, ak types.AccountKeeper) Keeper { + return Keeper{ + cdc: cdc, + storeKey: storeKey, + authKeeper: ak, + } +} + +// Logger returns a module-specific logger. +func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) +} + +// GrantFeeAllowance creates a new grant +func (k Keeper) GrantFeeAllowance(ctx sdk.Context, granter, grantee sdk.AccAddress, feeAllowance types.FeeAllowanceI) error { + + // create the account if it is not in account state + granteeAcc := k.authKeeper.GetAccount(ctx, grantee) + if granteeAcc == nil { + granteeAcc = k.authKeeper.NewAccountWithAddress(ctx, grantee) + k.authKeeper.SetAccount(ctx, granteeAcc) + } + + store := ctx.KVStore(k.storeKey) + key := types.FeeAllowanceKey(granter, grantee) + grant, err := types.NewFeeAllowanceGrant(granter, grantee, feeAllowance) + if err != nil { + return err + } + + bz, err := k.cdc.MarshalBinaryBare(&grant) + if err != nil { + return err + } + + store.Set(key, bz) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeSetFeeGrant, + sdk.NewAttribute(types.AttributeKeyGranter, grant.Granter), + sdk.NewAttribute(types.AttributeKeyGrantee, grant.Grantee), + ), + ) + + return nil +} + +// RevokeFeeAllowance removes an existing grant +func (k Keeper) RevokeFeeAllowance(ctx sdk.Context, granter, grantee sdk.AccAddress) error { + store := ctx.KVStore(k.storeKey) + key := types.FeeAllowanceKey(granter, grantee) + _, found := k.GetFeeGrant(ctx, granter, grantee) + if !found { + return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "fee-grant not found") + } + + store.Delete(key) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeRevokeFeeGrant, + sdk.NewAttribute(types.AttributeKeyGranter, granter.String()), + sdk.NewAttribute(types.AttributeKeyGrantee, grantee.String()), + ), + ) + return nil +} + +// GetFeeAllowance returns the allowance between the granter and grantee. +// If there is none, it returns nil, nil. +// Returns an error on parsing issues +func (k Keeper) GetFeeAllowance(ctx sdk.Context, granter, grantee sdk.AccAddress) types.FeeAllowanceI { + grant, found := k.GetFeeGrant(ctx, granter, grantee) + if !found { + return nil + } + + return grant.GetFeeGrant() +} + +// GetFeeGrant returns entire grant between both accounts +func (k Keeper) GetFeeGrant(ctx sdk.Context, granter sdk.AccAddress, grantee sdk.AccAddress) (types.FeeAllowanceGrant, bool) { + store := ctx.KVStore(k.storeKey) + key := types.FeeAllowanceKey(granter, grantee) + bz := store.Get(key) + if len(bz) == 0 { + return types.FeeAllowanceGrant{}, false + } + + var feegrant types.FeeAllowanceGrant + k.cdc.MustUnmarshalBinaryBare(bz, &feegrant) + + return feegrant, true +} + +// IterateAllGranteeFeeAllowances iterates over all the grants from anyone to the given grantee. +// Callback to get all data, returns true to stop, false to keep reading +func (k Keeper) IterateAllGranteeFeeAllowances(ctx sdk.Context, grantee sdk.AccAddress, cb func(types.FeeAllowanceGrant) bool) error { + store := ctx.KVStore(k.storeKey) + prefix := types.FeeAllowancePrefixByGrantee(grantee) + iter := sdk.KVStorePrefixIterator(store, prefix) + defer iter.Close() + + stop := false + for ; iter.Valid() && !stop; iter.Next() { + bz := iter.Value() + + var feeGrant types.FeeAllowanceGrant + k.cdc.MustUnmarshalBinaryBare(bz, &feeGrant) + + stop = cb(feeGrant) + } + + return nil +} + +// IterateAllFeeAllowances iterates over all the grants in the store. +// Callback to get all data, returns true to stop, false to keep reading +// Calling this without pagination is very expensive and only designed for export genesis +func (k Keeper) IterateAllFeeAllowances(ctx sdk.Context, cb func(types.FeeAllowanceGrant) bool) error { + store := ctx.KVStore(k.storeKey) + iter := sdk.KVStorePrefixIterator(store, types.FeeAllowanceKeyPrefix) + defer iter.Close() + + stop := false + for ; iter.Valid() && !stop; iter.Next() { + bz := iter.Value() + var feeGrant types.FeeAllowanceGrant + k.cdc.MustUnmarshalBinaryBare(bz, &feeGrant) + + stop = cb(feeGrant) + } + + return nil +} + +// UseGrantedFees will try to pay the given fee from the granter's account as requested by the grantee +func (k Keeper) UseGrantedFees(ctx sdk.Context, granter, grantee sdk.AccAddress, fee sdk.Coins) error { + grant, found := k.GetFeeGrant(ctx, granter, grantee) + if !found || grant.GetFeeGrant() == nil { + return sdkerrors.Wrapf(types.ErrNoAllowance, "grant missing") + } + + remove, err := grant.GetFeeGrant().Accept(fee, ctx.BlockTime(), ctx.BlockHeight()) + if err == nil { + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeUseFeeGrant, + sdk.NewAttribute(types.AttributeKeyGranter, granter.String()), + sdk.NewAttribute(types.AttributeKeyGrantee, grantee.String()), + ), + ) + } + + if remove { + k.RevokeFeeAllowance(ctx, granter, grantee) + // note this returns nil if err == nil + return sdkerrors.Wrap(err, "removed grant") + } + + if err != nil { + return sdkerrors.Wrap(err, "invalid grant") + } + + // if we accepted, store the updated state of the allowance + return k.GrantFeeAllowance(ctx, granter, grantee, grant.GetFeeGrant()) +} diff --git a/x/feegrant/keeper/keeper_test.go b/x/feegrant/keeper/keeper_test.go new file mode 100644 index 000000000000..c14e141d31f0 --- /dev/null +++ b/x/feegrant/keeper/keeper_test.go @@ -0,0 +1,257 @@ +package keeper_test + +import ( + "testing" + + "github.com/stretchr/testify/suite" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +type KeeperTestSuite struct { + suite.Suite + + app *simapp.SimApp + ctx sdk.Context + addrs []sdk.AccAddress +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(KeeperTestSuite)) +} + +func (suite *KeeperTestSuite) SetupTest() { + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, tmproto.Header{}) + + suite.app = app + suite.ctx = ctx + suite.addrs = simapp.AddTestAddrsIncremental(app, ctx, 4, sdk.NewInt(30000000)) +} + +func (suite *KeeperTestSuite) TestKeeperCrud() { + ctx := suite.ctx + k := suite.app.FeeGrantKeeper + + // some helpers + atom := sdk.NewCoins(sdk.NewInt64Coin("atom", 555)) + eth := sdk.NewCoins(sdk.NewInt64Coin("eth", 123)) + basic := &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(334455), + } + + basic2 := &types.BasicFeeAllowance{ + SpendLimit: eth, + Expiration: types.ExpiresAtHeight(172436), + } + + // let's set up some initial state here + err := k.GrantFeeAllowance(ctx, suite.addrs[0], suite.addrs[1], basic) + suite.Require().NoError(err) + + err = k.GrantFeeAllowance(ctx, suite.addrs[0], suite.addrs[2], basic2) + suite.Require().NoError(err) + + err = k.GrantFeeAllowance(ctx, suite.addrs[1], suite.addrs[2], basic) + suite.Require().NoError(err) + + err = k.GrantFeeAllowance(ctx, suite.addrs[1], suite.addrs[3], basic) + suite.Require().NoError(err) + + err = k.GrantFeeAllowance(ctx, suite.addrs[3], suite.addrs[0], basic2) + suite.Require().NoError(err) + + // remove some, overwrite other + k.RevokeFeeAllowance(ctx, suite.addrs[0], suite.addrs[1]) + k.RevokeFeeAllowance(ctx, suite.addrs[0], suite.addrs[2]) + + err = k.GrantFeeAllowance(ctx, suite.addrs[0], suite.addrs[2], basic) + suite.Require().NoError(err) + + err = k.GrantFeeAllowance(ctx, suite.addrs[1], suite.addrs[2], basic2) + suite.Require().NoError(err) + + // end state: + // addr -> addr3 (basic) + // addr2 -> addr3 (basic2), addr4(basic) + // addr4 -> addr (basic2) + + // then lots of queries + cases := map[string]struct { + grantee sdk.AccAddress + granter sdk.AccAddress + allowance types.FeeAllowanceI + }{ + "addr revoked": { + granter: suite.addrs[0], + grantee: suite.addrs[1], + }, + "addr revoked and added": { + granter: suite.addrs[0], + grantee: suite.addrs[2], + allowance: basic, + }, + "addr never there": { + granter: suite.addrs[0], + grantee: suite.addrs[3], + }, + "addr modified": { + granter: suite.addrs[1], + grantee: suite.addrs[2], + allowance: basic2, + }, + } + + for name, tc := range cases { + tc := tc + suite.Run(name, func() { + allow := k.GetFeeAllowance(ctx, tc.granter, tc.grantee) + if tc.allowance == nil { + suite.Nil(allow) + return + } + suite.NotNil(allow) + suite.Equal(tc.allowance, allow) + }) + } + + grant1, err := types.NewFeeAllowanceGrant(suite.addrs[3], suite.addrs[0], basic2) + suite.NoError(err) + + grant2, err := types.NewFeeAllowanceGrant(suite.addrs[1], suite.addrs[2], basic2) + suite.NoError(err) + + grant3, err := types.NewFeeAllowanceGrant(suite.addrs[0], suite.addrs[2], basic) + suite.NoError(err) + + allCases := map[string]struct { + grantee sdk.AccAddress + grants []types.FeeAllowanceGrant + }{ + "addr2 has none": { + grantee: suite.addrs[1], + }, + "addr has one": { + grantee: suite.addrs[0], + grants: []types.FeeAllowanceGrant{ + grant1, + }, + }, + "addr3 has two": { + grantee: suite.addrs[2], + grants: []types.FeeAllowanceGrant{ + grant3, + grant2, + }, + }, + } + + for name, tc := range allCases { + tc := tc + suite.Run(name, func() { + var grants []types.FeeAllowanceGrant + err := k.IterateAllGranteeFeeAllowances(ctx, tc.grantee, func(grant types.FeeAllowanceGrant) bool { + grants = append(grants, grant) + return false + }) + suite.NoError(err) + suite.Equal(tc.grants, grants) + }) + } +} + +func (suite *KeeperTestSuite) TestUseGrantedFee() { + ctx := suite.ctx + k := suite.app.FeeGrantKeeper + + // some helpers + atom := sdk.NewCoins(sdk.NewInt64Coin("atom", 555)) + eth := sdk.NewCoins(sdk.NewInt64Coin("eth", 123)) + future := &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(5678), + } + + expired := &types.BasicFeeAllowance{ + SpendLimit: eth, + Expiration: types.ExpiresAtHeight(55), + } + + // for testing limits of the contract + hugeAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 9999)) + _ = hugeAtom + smallAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 1)) + _ = smallAtom + futureAfterSmall := &types.BasicFeeAllowance{ + SpendLimit: sdk.NewCoins(sdk.NewInt64Coin("atom", 554)), + Expiration: types.ExpiresAtHeight(5678), + } + + // then lots of queries + cases := map[string]struct { + grantee sdk.AccAddress + granter sdk.AccAddress + fee sdk.Coins + allowed bool + final types.FeeAllowanceI + }{ + "use entire pot": { + granter: suite.addrs[0], + grantee: suite.addrs[1], + fee: atom, + allowed: true, + final: nil, + }, + "expired and removed": { + granter: suite.addrs[0], + grantee: suite.addrs[2], + fee: eth, + allowed: false, + final: nil, + }, + "too high": { + granter: suite.addrs[0], + grantee: suite.addrs[1], + fee: hugeAtom, + allowed: false, + final: future, + }, + "use a little": { + granter: suite.addrs[0], + grantee: suite.addrs[1], + fee: smallAtom, + allowed: true, + final: futureAfterSmall, + }, + } + + for name, tc := range cases { + tc := tc + suite.Run(name, func() { + // let's set up some initial state here + // addr -> addr2 (future) + // addr -> addr3 (expired) + + err := k.GrantFeeAllowance(ctx, suite.addrs[0], suite.addrs[1], future) + suite.Require().NoError(err) + + err = k.GrantFeeAllowance(ctx, suite.addrs[0], suite.addrs[3], expired) + suite.Require().NoError(err) + + err = k.UseGrantedFees(ctx, tc.granter, tc.grantee, tc.fee) + if tc.allowed { + suite.NoError(err) + } else { + suite.Error(err) + } + + loaded := k.GetFeeAllowance(ctx, tc.granter, tc.grantee) + + suite.Equal(tc.final, loaded) + }) + } +} diff --git a/x/feegrant/keeper/msg_server.go b/x/feegrant/keeper/msg_server.go new file mode 100644 index 000000000000..3cd96e79ba88 --- /dev/null +++ b/x/feegrant/keeper/msg_server.go @@ -0,0 +1,72 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +type msgServer struct { + Keeper +} + +// NewMsgServerImpl returns an implementation of the feegrant MsgServer interface +// for the provided Keeper. +func NewMsgServerImpl(k Keeper) types.MsgServer { + return &msgServer{ + Keeper: k, + } +} + +var _ types.MsgServer = msgServer{} + +func (k msgServer) GrantFeeAllowance(goCtx context.Context, msg *types.MsgGrantFeeAllowance) (*types.MsgGrantFeeAllowanceResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + grantee, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + return nil, err + } + + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + return nil, err + } + + // Checking for duplicate entry + f := k.Keeper.GetFeeAllowance(ctx, granter, grantee) + if f != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "fee allowance already exists") + } + + err = k.Keeper.GrantFeeAllowance(ctx, granter, grantee, msg.GetFeeAllowanceI()) + if err != nil { + return nil, err + } + + return &types.MsgGrantFeeAllowanceResponse{}, nil +} + +func (k msgServer) RevokeFeeAllowance(goCtx context.Context, msg *types.MsgRevokeFeeAllowance) (*types.MsgRevokeFeeAllowanceResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + grantee, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + return nil, err + } + + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + return nil, err + } + + err = k.Keeper.RevokeFeeAllowance(ctx, granter, grantee) + if err != nil { + return nil, err + } + + return &types.MsgRevokeFeeAllowanceResponse{}, nil +} diff --git a/x/feegrant/module.go b/x/feegrant/module.go new file mode 100644 index 000000000000..5f4ba807d895 --- /dev/null +++ b/x/feegrant/module.go @@ -0,0 +1,210 @@ +package feegrant + +import ( + "context" + "encoding/json" + "math/rand" + + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + abci "github.com/tendermint/tendermint/abci/types" + + sdkclient "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/client/cli" + "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + "github.com/cosmos/cosmos-sdk/x/feegrant/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} + _ module.AppModuleSimulation = AppModule{} +) + +// ---------------------------------------------------------------------------- +// AppModuleBasic +// ---------------------------------------------------------------------------- + +// AppModuleBasic defines the basic application module used by the feegrant module. +type AppModuleBasic struct { + cdc codec.Marshaler +} + +// Name returns the feegrant module's name. +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterServices registers a gRPC query service to respond to the +// module-specific gRPC queries. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) + types.RegisterQueryServer(cfg.QueryServer(), am.keeper) +} + +// RegisterLegacyAminoCodec registers the feegrant module's types for the given codec. +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { +} + +// RegisterInterfaces registers the feegrant module's interface types +func (AppModuleBasic) RegisterInterfaces(registry cdctypes.InterfaceRegistry) { + types.RegisterInterfaces(registry) +} + +// LegacyQuerierHandler returns the feegrant module sdk.Querier. +func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier { + return nil +} + +// DefaultGenesis returns default genesis state as raw bytes for the feegrant +// module. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONMarshaler) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesisState()) +} + +// ValidateGenesis performs genesis state validation for the feegrant module. +func (a AppModuleBasic) ValidateGenesis(cdc codec.JSONMarshaler, config sdkclient.TxEncodingConfig, bz json.RawMessage) error { + var data types.GenesisState + if err := cdc.UnmarshalJSON(bz, &data); err != nil { + sdkerrors.Wrapf(err, "failed to unmarshal %s genesis state", types.ModuleName) + } + + return types.ValidateGenesis(data) +} + +// RegisterRESTRoutes registers the REST routes for the feegrant module. +func (AppModuleBasic) RegisterRESTRoutes(ctx sdkclient.Context, rtr *mux.Router) {} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the feegrant module. +func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx sdkclient.Context, mux *runtime.ServeMux) { + types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) +} + +// GetTxCmd returns the root tx command for the feegrant module. +func (AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.GetTxCmd() +} + +// GetQueryCmd returns no root query command for the feegrant module. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() +} + +// ---------------------------------------------------------------------------- +// AppModule +// ---------------------------------------------------------------------------- + +// AppModule implements an application module for the feegrant module. +type AppModule struct { + AppModuleBasic + keeper keeper.Keeper + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper + registry cdctypes.InterfaceRegistry +} + +// NewAppModule creates a new AppModule object +func NewAppModule(cdc codec.Marshaler, ak types.AccountKeeper, bk types.BankKeeper, keeper keeper.Keeper, registry cdctypes.InterfaceRegistry) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{cdc: cdc}, + keeper: keeper, + accountKeeper: ak, + bankKeeper: bk, + registry: registry, + } +} + +// Name returns the feegrant module's name. +func (AppModule) Name() string { + return types.ModuleName +} + +// RegisterInvariants registers the feegrant module invariants. +func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {} + +// Route returns the message routing key for the feegrant module. +func (am AppModule) Route() sdk.Route { + return sdk.NewRoute(types.RouterKey, nil) +} + +// NewHandler returns an sdk.Handler for the feegrant module. +func (am AppModule) NewHandler() sdk.Handler { + return nil +} + +// QuerierRoute returns the feegrant module's querier route name. +func (AppModule) QuerierRoute() string { + return "" +} + +// InitGenesis performs genesis initialization for the feegrant module. It returns +// no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONMarshaler, bz json.RawMessage) []abci.ValidatorUpdate { + var gs types.GenesisState + cdc.MustUnmarshalJSON(bz, &gs) + + InitGenesis(ctx, am.keeper, &gs) + return []abci.ValidatorUpdate{} +} + +// ExportGenesis returns the exported genesis state as raw bytes for the feegrant +// module. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json.RawMessage { + gs, err := ExportGenesis(ctx, am.keeper) + if err != nil { + panic(err) + } + + return cdc.MustMarshalJSON(gs) +} + +// BeginBlock returns the begin blocker for the feegrant module. +func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} + +// EndBlock returns the end blocker for the feegrant module. It returns no validator +// updates. +func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +//____________________________________________________________________________ + +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenState of the feegrant module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + simulation.RandomizedGenState(simState) +} + +// ProposalContents returns all the feegrant content functions used to +// simulate governance proposals. +func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent { + return nil +} + +// RandomizedParams creates randomized feegrant param changes for the simulator. +func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange { + return nil +} + +// RegisterStoreDecoder registers a decoder for feegrant module's types +func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { + sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) +} + +// WeightedOperations returns all the feegrant module operations with their respective weights. +func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { + protoCdc := codec.NewProtoCodec(am.registry) + return simulation.WeightedOperations( + simState.AppParams, simState.Cdc, am.accountKeeper, am.bankKeeper, am.keeper, protoCdc, + ) +} diff --git a/x/feegrant/simulation/decoder.go b/x/feegrant/simulation/decoder.go new file mode 100644 index 000000000000..46e35594fdf8 --- /dev/null +++ b/x/feegrant/simulation/decoder.go @@ -0,0 +1,26 @@ +package simulation + +import ( + "bytes" + "fmt" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/types/kv" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's +// Value to the corresponding feegrant type. +func NewDecodeStore(cdc codec.Marshaler) func(kvA, kvB kv.Pair) string { + return func(kvA, kvB kv.Pair) string { + switch { + case bytes.Equal(kvA.Key[:1], types.FeeAllowanceKeyPrefix): + var grantA, grantB types.FeeAllowanceGrant + cdc.MustUnmarshalBinaryBare(kvA.Value, &grantA) + cdc.MustUnmarshalBinaryBare(kvB.Value, &grantB) + return fmt.Sprintf("%v\n%v", grantA, grantB) + default: + panic(fmt.Sprintf("invalid feegrant key %X", kvA.Key)) + } + } +} diff --git a/x/feegrant/simulation/decoder_test.go b/x/feegrant/simulation/decoder_test.go new file mode 100644 index 000000000000..0087e5eba117 --- /dev/null +++ b/x/feegrant/simulation/decoder_test.go @@ -0,0 +1,62 @@ +package simulation_test + +import ( + "fmt" + "testing" + + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/kv" + "github.com/cosmos/cosmos-sdk/x/feegrant/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/stretchr/testify/require" +) + +var ( + granterPk = ed25519.GenPrivKey().PubKey() + granterAddr = sdk.AccAddress(granterPk.Address()) + granteePk = ed25519.GenPrivKey().PubKey() + granteeAddr = sdk.AccAddress(granterPk.Address()) +) + +func TestDecodeStore(t *testing.T) { + cdc := simapp.MakeTestEncodingConfig().Marshaler + dec := simulation.NewDecodeStore(cdc) + + grant, err := types.NewFeeAllowanceGrant(granterAddr, granteeAddr, &types.BasicFeeAllowance{ + SpendLimit: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(100))), + }) + + require.NoError(t, err) + + grantBz, err := cdc.MarshalBinaryBare(&grant) + require.NoError(t, err) + + kvPairs := kv.Pairs{ + Pairs: []kv.Pair{ + {Key: []byte(types.FeeAllowanceKeyPrefix), Value: grantBz}, + {Key: []byte{0x99}, Value: []byte{0x99}}, + }, + } + + tests := []struct { + name string + expectedLog string + }{ + {"Grant", fmt.Sprintf("%v\n%v", grant, grant)}, + {"other", ""}, + } + + for i, tt := range tests { + i, tt := i, tt + t.Run(tt.name, func(t *testing.T) { + switch i { + case len(tests) - 1: + require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) + default: + require.Equal(t, tt.expectedLog, dec(kvPairs.Pairs[i], kvPairs.Pairs[i]), tt.name) + } + }) + } +} diff --git a/x/feegrant/simulation/genesis.go b/x/feegrant/simulation/genesis.go new file mode 100644 index 000000000000..f9f4c7e12748 --- /dev/null +++ b/x/feegrant/simulation/genesis.go @@ -0,0 +1,38 @@ +package simulation + +import ( + "encoding/json" + "fmt" + "math/rand" + + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +// Simulation parameter constants +const feegrant = "feegrant" + +// GenFeeGrants returns an empty slice of evidences. +func GenFeeGrants(_ *rand.Rand, _ []simtypes.Account) []types.FeeAllowanceGrant { + return []types.FeeAllowanceGrant{} +} + +// RandomizedGenState generates a random GenesisState for feegrant +func RandomizedGenState(simState *module.SimulationState) { + var feegrants []types.FeeAllowanceGrant + + simState.AppParams.GetOrGenerate( + simState.Cdc, feegrant, &feegrants, simState.Rand, + func(r *rand.Rand) { feegrants = GenFeeGrants(r, simState.Accounts) }, + ) + feegrantGenesis := types.NewGenesisState(feegrants) + + bz, err := json.MarshalIndent(&feegrantGenesis, "", " ") + if err != nil { + panic(err) + } + + fmt.Printf("Selected randomly generated %s parameters:\n%s\n", types.ModuleName, bz) + simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(feegrantGenesis) +} diff --git a/x/feegrant/simulation/genesis_test.go b/x/feegrant/simulation/genesis_test.go new file mode 100644 index 000000000000..4f3ae74b56be --- /dev/null +++ b/x/feegrant/simulation/genesis_test.go @@ -0,0 +1,39 @@ +package simulation_test + +import ( + "encoding/json" + "math/rand" + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/stretchr/testify/require" +) + +func TestRandomizedGenState(t *testing.T) { + interfaceRegistry := codectypes.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + s := rand.NewSource(1) + r := rand.New(s) + + simState := module.SimulationState{ + AppParams: make(simtypes.AppParams), + Cdc: cdc, + Rand: r, + NumBonded: 3, + Accounts: simtypes.RandomAccounts(r, 3), + InitialStake: 1000, + GenState: make(map[string]json.RawMessage), + } + + simulation.RandomizedGenState(&simState) + var feegrantGenesis types.GenesisState + simState.Cdc.MustUnmarshalJSON(simState.GenState[types.ModuleName], &feegrantGenesis) + + require.Len(t, feegrantGenesis.FeeAllowances, 0) +} diff --git a/x/feegrant/simulation/operations.go b/x/feegrant/simulation/operations.go new file mode 100644 index 000000000000..54821873b6b6 --- /dev/null +++ b/x/feegrant/simulation/operations.go @@ -0,0 +1,200 @@ +package simulation + +import ( + "context" + "math/rand" + "time" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simapp/helpers" + simappparams "github.com/cosmos/cosmos-sdk/simapp/params" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/cosmos/cosmos-sdk/x/simulation" +) + +// Simulation operation weights constants +const ( + OpWeightMsgGrantFeeAllowance = "op_weight_msg_grant_fee_allowance" + OpWeightMsgRevokeFeeAllowance = "op_weight_msg_grant_revoke_allowance" + TypeMsgGrantFeeAllowance = "/cosmos.feegrant.v1beta1.Msg/GrantFeeAllowance" + TypeMsgRevokeFeeAllowance = "/cosmos.feegrant.v1beta1.Msg/RevokeFeeAllowance" +) + +func WeightedOperations( + appParams simtypes.AppParams, cdc codec.JSONMarshaler, + ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, + protoCdc *codec.ProtoCodec, +) simulation.WeightedOperations { + + var ( + weightMsgGrantFeeAllowance int + weightMsgRevokeFeeAllowance int + ) + + appParams.GetOrGenerate(cdc, OpWeightMsgGrantFeeAllowance, &weightMsgGrantFeeAllowance, nil, + func(_ *rand.Rand) { + weightMsgGrantFeeAllowance = simappparams.DefaultWeightGrantFeeAllowance + }, + ) + + appParams.GetOrGenerate(cdc, OpWeightMsgRevokeFeeAllowance, &weightMsgRevokeFeeAllowance, nil, + func(_ *rand.Rand) { + weightMsgRevokeFeeAllowance = simappparams.DefaultWeightRevokeFeeAllowance + }, + ) + + return simulation.WeightedOperations{ + simulation.NewWeightedOperation( + weightMsgGrantFeeAllowance, + SimulateMsgGrantFeeAllowance(ak, bk, k, protoCdc), + ), + simulation.NewWeightedOperation( + weightMsgRevokeFeeAllowance, + SimulateMsgRevokeFeeAllowance(ak, bk, k, protoCdc), + ), + } +} + +// SimulateMsgGrantFeeAllowance generates MsgGrantFeeAllowance with random values. +func SimulateMsgGrantFeeAllowance(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + granter, _ := simtypes.RandomAcc(r, accs) + grantee, _ := simtypes.RandomAcc(r, accs) + if grantee.Address.String() == granter.Address.String() { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgGrantFeeAllowance, "grantee and granter cannot be same"), nil, nil + } + + f := k.GetFeeAllowance(ctx, granter.Address, grantee.Address) + if f != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgGrantFeeAllowance, "fee allowance exists"), nil, nil + } + + account := ak.GetAccount(ctx, granter.Address) + + spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, ctx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgGrantFeeAllowance, err.Error()), nil, err + } + + spendableCoins = spendableCoins.Sub(fees) + if spendableCoins.Empty() { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgGrantFeeAllowance, "unable to grant empty coins as SpendLimit"), nil, nil + } + + msg, err := types.NewMsgGrantFeeAllowance(&types.BasicFeeAllowance{ + SpendLimit: spendableCoins, + Expiration: types.ExpiresAtTime(ctx.BlockTime().Add(30 * time.Hour)), + }, granter.Address, grantee.Address) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgGrantFeeAllowance, err.Error()), nil, err + } + txGen := simappparams.MakeTestEncodingConfig().TxConfig + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + feegrantMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = feegrantMsgClient.GrantFeeAllowance(context.Background(), msg) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgGrantFeeAllowance, err.Error()), nil, err + } + tx, err := helpers.GenTx( + txGen, + svcMsgClientConn.GetMsgs(), + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + granter.PrivKey, + ) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgGrantFeeAllowance, "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, svcMsgClientConn.GetMsgs()[0].Type(), "unable to deliver tx"), nil, err + } + return simtypes.NewOperationMsg(svcMsgClientConn.GetMsgs()[0], true, "", protoCdc), nil, err + } +} + +// SimulateMsgRevokeFeeAllowance generates a MsgRevokeFeeAllowance with random values. +func SimulateMsgRevokeFeeAllowance(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + hasGrant := false + var granterAddr sdk.AccAddress + var granteeAddr sdk.AccAddress + k.IterateAllFeeAllowances(ctx, func(grant types.FeeAllowanceGrant) bool { + + granter, err := sdk.AccAddressFromBech32(grant.Granter) + if err != nil { + panic(err) + } + grantee, err := sdk.AccAddressFromBech32(grant.Grantee) + if err != nil { + panic(err) + } + granterAddr = granter + granteeAddr = grantee + hasGrant = true + return true + }) + + if !hasGrant { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeFeeAllowance, "no grants"), nil, nil + } + granter, ok := simtypes.FindAccount(accs, granterAddr) + + if !ok { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeFeeAllowance, "Account not found"), nil, nil + } + + account := ak.GetAccount(ctx, granter.Address) + spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, ctx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeFeeAllowance, err.Error()), nil, err + } + + msg := types.NewMsgRevokeFeeAllowance(granterAddr, granteeAddr) + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + feegrantMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = feegrantMsgClient.RevokeFeeAllowance(context.Background(), &msg) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgGrantFeeAllowance, err.Error()), nil, err + } + + tx, err := helpers.GenTx( + txGen, + svcMsgClientConn.GetMsgs(), + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + granter.PrivKey, + ) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeFeeAllowance, err.Error()), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + return simtypes.NewOperationMsg(svcMsgClientConn.GetMsgs()[0], true, "", protoCdc), nil, err + } +} diff --git a/x/feegrant/simulation/operations_test.go b/x/feegrant/simulation/operations_test.go new file mode 100644 index 000000000000..7c2593a5302a --- /dev/null +++ b/x/feegrant/simulation/operations_test.go @@ -0,0 +1,173 @@ +package simulation_test + +import ( + "math/rand" + "testing" + "time" + + "github.com/stretchr/testify/suite" + + abci "github.com/tendermint/tendermint/abci/types" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simapp" + simappparams "github.com/cosmos/cosmos-sdk/simapp/params" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +type SimTestSuite struct { + suite.Suite + + ctx sdk.Context + app *simapp.SimApp + protoCdc *codec.ProtoCodec +} + +func (suite *SimTestSuite) SetupTest() { + checkTx := false + app := simapp.Setup(checkTx) + suite.app = app + suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{}) + suite.protoCdc = codec.NewProtoCodec(suite.app.InterfaceRegistry()) + +} + +func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { + app, ctx := suite.app, suite.ctx + accounts := simtypes.RandomAccounts(r, n) + require := suite.Require() + + initAmt := sdk.TokensFromConsensusPower(200) + initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) + + // add coins to the accounts + for _, account := range accounts { + acc := app.AccountKeeper.NewAccountWithAddress(ctx, account.Address) + app.AccountKeeper.SetAccount(ctx, acc) + err := app.BankKeeper.SetBalances(ctx, account.Address, initCoins) + require.NoError(err) + } + + return accounts +} + +func (suite *SimTestSuite) TestWeightedOperations() { + app, ctx := suite.app, suite.ctx + require := suite.Require() + + ctx.WithChainID("test-chain") + + cdc := app.AppCodec() + appParams := make(simtypes.AppParams) + + weightesOps := simulation.WeightedOperations( + appParams, cdc, app.AccountKeeper, + app.BankKeeper, app.FeeGrantKeeper, + suite.protoCdc, + ) + + s := rand.NewSource(1) + r := rand.New(s) + accs := suite.getTestingAccounts(r, 3) + + expected := []struct { + weight int + opMsgRoute string + opMsgName string + }{ + { + simappparams.DefaultWeightGrantFeeAllowance, + types.ModuleName, + simulation.TypeMsgGrantFeeAllowance, + }, + { + simappparams.DefaultWeightRevokeFeeAllowance, + types.ModuleName, + simulation.TypeMsgRevokeFeeAllowance, + }, + } + + for i, w := range weightesOps { + operationMsg, _, _ := w.Op()(r, app.BaseApp, ctx, accs, ctx.ChainID()) + // the following checks are very much dependent from the ordering of the output given + // by WeightedOperations. if the ordering in WeightedOperations changes some tests + // will fail + require.Equal(expected[i].weight, w.Weight(), "weight should be the same") + require.Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") + require.Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") + } +} + +func (suite *SimTestSuite) TestSimulateMsgGrantFeeAllowance() { + app, ctx := suite.app, suite.ctx + require := suite.Require() + + s := rand.NewSource(1) + r := rand.New(s) + accounts := suite.getTestingAccounts(r, 3) + + // begin a new block + app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: app.LastBlockHeight() + 1, AppHash: app.LastCommitID().Hash}}) + + // execute operation + op := simulation.SimulateMsgGrantFeeAllowance(app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, suite.protoCdc) + operationMsg, futureOperations, err := op(r, app.BaseApp, ctx, accounts, "") + require.NoError(err) + + var msg types.MsgGrantFeeAllowance + suite.app.AppCodec().UnmarshalJSON(operationMsg.Msg, &msg) + + require.True(operationMsg.OK) + require.Equal("cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Granter) + require.Equal("cosmos1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7u4x9a0", msg.Grantee) + require.Len(futureOperations, 0) +} + +func (suite *SimTestSuite) TestSimulateMsgRevokeFeeAllowance() { + app, ctx := suite.app, suite.ctx + require := suite.Require() + + s := rand.NewSource(1) + r := rand.New(s) + accounts := suite.getTestingAccounts(r, 3) + + // begin a new block + app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: suite.app.LastBlockHeight() + 1, AppHash: suite.app.LastCommitID().Hash}}) + + feeAmt := sdk.TokensFromConsensusPower(200000) + feeCoins := sdk.NewCoins(sdk.NewCoin("foo", feeAmt)) + + granter, grantee := accounts[0], accounts[1] + + err := app.FeeGrantKeeper.GrantFeeAllowance( + ctx, + granter.Address, + grantee.Address, + &types.BasicFeeAllowance{ + SpendLimit: feeCoins, + Expiration: types.ExpiresAtTime(ctx.BlockTime().Add(30 * time.Hour)), + }, + ) + require.NoError(err) + + // execute operation + op := simulation.SimulateMsgRevokeFeeAllowance(app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, suite.protoCdc) + operationMsg, futureOperations, err := op(r, app.BaseApp, ctx, accounts, "") + require.NoError(err) + + var msg types.MsgRevokeFeeAllowance + suite.app.AppCodec().UnmarshalJSON(operationMsg.Msg, &msg) + + require.True(operationMsg.OK) + require.Equal(granter.Address.String(), msg.Granter) + require.Equal(grantee.Address.String(), msg.Grantee) + require.Len(futureOperations, 0) +} + +func TestSimTestSuite(t *testing.T) { + suite.Run(t, new(SimTestSuite)) +} diff --git a/x/feegrant/types/basic_fee.go b/x/feegrant/types/basic_fee.go new file mode 100644 index 000000000000..6d970680510f --- /dev/null +++ b/x/feegrant/types/basic_fee.go @@ -0,0 +1,61 @@ +package types + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +var _ FeeAllowanceI = (*BasicFeeAllowance)(nil) + +// Accept can use fee payment requested as well as timestamp/height of the current block +// to determine whether or not to process this. This is checked in +// Keeper.UseGrantedFees and the return values should match how it is handled there. +// +// If it returns an error, the fee payment is rejected, otherwise it is accepted. +// The FeeAllowance implementation is expected to update it's internal state +// and will be saved again after an acceptance. +// +// If remove is true (regardless of the error), the FeeAllowance will be deleted from storage +// (eg. when it is used up). (See call to RevokeFeeAllowance in Keeper.UseGrantedFees) +func (a *BasicFeeAllowance) Accept(fee sdk.Coins, blockTime time.Time, blockHeight int64) (bool, error) { + if a.Expiration.IsExpired(&blockTime, blockHeight) { + return true, sdkerrors.Wrap(ErrFeeLimitExpired, "basic allowance") + } + + if a.SpendLimit != nil { + left, invalid := a.SpendLimit.SafeSub(fee) + if invalid { + return false, sdkerrors.Wrap(ErrFeeLimitExceeded, "basic allowance") + } + + a.SpendLimit = left + return left.IsZero(), nil + } + + return false, nil +} + +// PrepareForExport will adjust the expiration based on export time. In particular, +// it will subtract the dumpHeight from any height-based expiration to ensure that +// the elapsed number of blocks this allowance is valid for is fixed. +func (a *BasicFeeAllowance) PrepareForExport(dumpTime time.Time, dumpHeight int64) FeeAllowanceI { + return &BasicFeeAllowance{ + SpendLimit: a.SpendLimit, + Expiration: a.Expiration.PrepareForExport(dumpTime, dumpHeight), + } +} + +// ValidateBasic implements FeeAllowance and enforces basic sanity checks +func (a BasicFeeAllowance) ValidateBasic() error { + if a.SpendLimit != nil { + if !a.SpendLimit.IsValid() { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "send amount is invalid: %s", a.SpendLimit) + } + if !a.SpendLimit.IsAllPositive() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "spend limit must be positive") + } + } + return a.Expiration.ValidateBasic() +} diff --git a/x/feegrant/types/basic_fee_test.go b/x/feegrant/types/basic_fee_test.go new file mode 100644 index 000000000000..a5669e99ada4 --- /dev/null +++ b/x/feegrant/types/basic_fee_test.go @@ -0,0 +1,140 @@ +package types_test + +import ( + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestBasicFeeValidAllow(t *testing.T) { + eth := sdk.NewCoins(sdk.NewInt64Coin("eth", 10)) + atom := sdk.NewCoins(sdk.NewInt64Coin("atom", 555)) + smallAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 43)) + bigAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 1000)) + leftAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 512)) + + cases := map[string]struct { + allow *types.BasicFeeAllowance + // all other checks are ignored if valid=false + fee sdk.Coins + blockTime time.Time + blockHeight int64 + valid bool + accept bool + remove bool + remains sdk.Coins + }{ + "empty": { + allow: &types.BasicFeeAllowance{}, + valid: true, + accept: true, + }, + "small fee without expire": { + allow: &types.BasicFeeAllowance{ + SpendLimit: atom, + }, + valid: true, + fee: smallAtom, + accept: true, + remove: false, + remains: leftAtom, + }, + "all fee without expire": { + allow: &types.BasicFeeAllowance{ + SpendLimit: smallAtom, + }, + valid: true, + fee: smallAtom, + accept: true, + remove: true, + }, + "wrong fee": { + allow: &types.BasicFeeAllowance{ + SpendLimit: smallAtom, + }, + valid: true, + fee: eth, + accept: false, + }, + "non-expired": { + allow: &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + valid: true, + fee: smallAtom, + blockHeight: 85, + accept: true, + remove: false, + remains: leftAtom, + }, + "expired": { + allow: &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + valid: true, + fee: smallAtom, + blockHeight: 121, + accept: false, + remove: true, + }, + "fee more than allowed": { + allow: &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + valid: true, + fee: bigAtom, + blockHeight: 85, + accept: false, + }, + "with out spend limit": { + allow: &types.BasicFeeAllowance{ + Expiration: types.ExpiresAtHeight(100), + }, + valid: true, + fee: bigAtom, + blockHeight: 85, + accept: true, + }, + "expired no spend limit": { + allow: &types.BasicFeeAllowance{ + Expiration: types.ExpiresAtHeight(100), + }, + valid: true, + fee: bigAtom, + blockHeight: 120, + accept: false, + }, + } + + for name, stc := range cases { + tc := stc // to make scopelint happy + t.Run(name, func(t *testing.T) { + err := tc.allow.ValidateBasic() + if !tc.valid { + require.Error(t, err) + return + } + require.NoError(t, err) + + // now try to deduct + remove, err := tc.allow.Accept(tc.fee, tc.blockTime, tc.blockHeight) + if !tc.accept { + require.Error(t, err) + return + } + require.NoError(t, err) + + require.Equal(t, tc.remove, remove) + if !remove { + assert.Equal(t, tc.allow.SpendLimit, tc.remains) + } + }) + } +} diff --git a/x/feegrant/types/codec.go b/x/feegrant/types/codec.go new file mode 100644 index 000000000000..686187cd7510 --- /dev/null +++ b/x/feegrant/types/codec.go @@ -0,0 +1,24 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" +) + +// RegisterInterfaces registers the interfaces types with the interface registry +func RegisterInterfaces(registry types.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.MsgRequest)(nil), + &MsgGrantFeeAllowance{}, + &MsgRevokeFeeAllowance{}, + ) + + registry.RegisterInterface( + "cosmos.feegrant.v1beta1.FeeAllowanceI", + (*FeeAllowanceI)(nil), + &BasicFeeAllowance{}, + &PeriodicFeeAllowance{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} diff --git a/x/feegrant/types/errors.go b/x/feegrant/types/errors.go new file mode 100644 index 000000000000..183f681ca5dc --- /dev/null +++ b/x/feegrant/types/errors.go @@ -0,0 +1,21 @@ +package types + +import ( + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// Codes for governance errors +const ( + DefaultCodespace = ModuleName +) + +var ( + // ErrFeeLimitExceeded error if there are not enough allowance to cover the fees + ErrFeeLimitExceeded = sdkerrors.Register(DefaultCodespace, 2, "fee limit exceeded") + // ErrFeeLimitExpired error if the allowance has expired + ErrFeeLimitExpired = sdkerrors.Register(DefaultCodespace, 3, "fee allowance expired") + // ErrInvalidDuration error if the Duration is invalid or doesn't match the expiration + ErrInvalidDuration = sdkerrors.Register(DefaultCodespace, 4, "invalid duration") + // ErrNoAllowance error if there is no allowance for that pair + ErrNoAllowance = sdkerrors.Register(DefaultCodespace, 5, "no allowance") +) diff --git a/x/feegrant/types/events.go b/x/feegrant/types/events.go new file mode 100644 index 000000000000..b82ccb7b1cd8 --- /dev/null +++ b/x/feegrant/types/events.go @@ -0,0 +1,13 @@ +package types + +// evidence module events +const ( + EventTypeUseFeeGrant = "use_feegrant" + EventTypeRevokeFeeGrant = "revoke_feegrant" + EventTypeSetFeeGrant = "set_feegrant" + + AttributeKeyGranter = "granter" + AttributeKeyGrantee = "grantee" + + AttributeValueCategory = ModuleName +) diff --git a/x/feegrant/types/expected_keepers.go b/x/feegrant/types/expected_keepers.go new file mode 100644 index 000000000000..40966b06d47f --- /dev/null +++ b/x/feegrant/types/expected_keepers.go @@ -0,0 +1,23 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + auth "github.com/cosmos/cosmos-sdk/x/auth/types" + // supply "github.com/cosmos/cosmos-sdk/x/supply/exported" +) + +// AccountKeeper defines the expected auth Account Keeper (noalias) +type AccountKeeper interface { + GetModuleAddress(moduleName string) sdk.AccAddress + GetModuleAccount(ctx sdk.Context, moduleName string) auth.ModuleAccountI + + NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) auth.AccountI + GetAccount(ctx sdk.Context, addr sdk.AccAddress) auth.AccountI + SetAccount(ctx sdk.Context, acc auth.AccountI) +} + +// BankKeeper defines the expected supply Keeper (noalias) +type BankKeeper interface { + SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins + SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error +} diff --git a/x/feegrant/types/expiration.go b/x/feegrant/types/expiration.go new file mode 100644 index 000000000000..4922b6d481d0 --- /dev/null +++ b/x/feegrant/types/expiration.go @@ -0,0 +1,138 @@ +package types + +import ( + "time" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// ExpiresAtTime creates an expiration at the given time +func ExpiresAtTime(t time.Time) ExpiresAt { + return ExpiresAt{ + Sum: &ExpiresAt_Time{ + Time: &t, + }, + } +} + +// ExpiresAtHeight creates an expiration at the given height +func ExpiresAtHeight(h int64) ExpiresAt { + return ExpiresAt{ + &ExpiresAt_Height{ + Height: h, + }, + } +} + +// ValidateBasic performs basic sanity checks. +// Note that empty expiration is allowed +func (e ExpiresAt) ValidateBasic() error { + if e.HasDefinedTime() && e.GetHeight() != 0 { + return sdkerrors.Wrap(ErrInvalidDuration, "both time and height are set") + } + if e.GetHeight() < 0 { + return sdkerrors.Wrap(ErrInvalidDuration, "negative height") + } + return nil +} + +// Undefined returns true for an uninitialized struct +func (e ExpiresAt) Undefined() bool { + return (e.GetTime() == nil || e.GetTime().Unix() <= 0) && e.GetHeight() == 0 +} + +// HasDefinedTime returns true if `ExpiresAt` has valid time +func (e ExpiresAt) HasDefinedTime() bool { + t := e.GetTime() + return t != nil && t.Unix() > 0 +} + +// FastForward produces a new Expiration with the time or height set to the +// new value, depending on what was set on the original expiration +func (e ExpiresAt) FastForward(t time.Time, h int64) ExpiresAt { + if e.HasDefinedTime() { + return ExpiresAtTime(t) + } + return ExpiresAtHeight(h) +} + +// IsExpired returns if the time or height is *equal to* or greater +// than the defined expiration point. Note that it is expired upon +// an exact match. +// +// Note a "zero" ExpiresAt is never expired +func (e ExpiresAt) IsExpired(t *time.Time, h int64) bool { + if e.HasDefinedTime() && t.After(*e.GetTime()) { + return true + } + + return e.GetHeight() != 0 && h >= e.GetHeight() +} + +// IsCompatible returns true iff the two use the same units. +// If false, they cannot be added. +func (e ExpiresAt) IsCompatible(d Duration) bool { + if e.HasDefinedTime() { + return d.GetDuration() != nil && d.GetDuration().Seconds() > float64(0) + } + return d.GetBlocks() > 0 +} + +// Step will increase the expiration point by one Duration +// It returns an error if the Duration is incompatible +func (e ExpiresAt) Step(d Duration) (ExpiresAt, error) { + if !e.IsCompatible(d) { + return ExpiresAt{}, sdkerrors.Wrap(ErrInvalidDuration, "expiration time and provided duration have different units") + } + if e.HasDefinedTime() { + return ExpiresAtTime(e.GetTime().Add(*d.GetDuration())), nil + } + return ExpiresAtHeight(e.GetHeight() + int64(d.GetBlocks())), nil +} + +// MustStep is like Step, but panics on error +func (e ExpiresAt) MustStep(d Duration) ExpiresAt { + res, err := e.Step(d) + if err != nil { + panic(err) + } + return res +} + +// PrepareForExport will deduct the dumpHeight from the expiration, so when this is +// reloaded after a hard fork, the actual number of allowed blocks is constant +func (e ExpiresAt) PrepareForExport(dumpTime time.Time, dumpHeight int64) ExpiresAt { + if e.GetHeight() != 0 { + return ExpiresAtHeight(e.GetHeight() - dumpHeight) + } + return ExpiresAt{} +} + +// ClockDuration creates an Duration by clock time +func ClockDuration(d time.Duration) Duration { + return Duration{Sum: &Duration_Duration{ + Duration: &d, + }} +} + +// BlockDuration creates an Duration by block height +func BlockDuration(h uint64) Duration { + return Duration{Sum: &Duration_Blocks{ + Blocks: h, + }} +} + +// ValidateBasic performs basic sanity checks +// Note that exactly one must be set and it must be positive +func (d Duration) ValidateBasic() error { + if d.GetBlocks() == 0 && d.GetDuration() == nil { + return sdkerrors.Wrap(ErrInvalidDuration, "neither time and height are set") + } + if d.GetBlocks() != 0 && d.GetDuration() != nil && d.GetDuration().Seconds() != float64(0) { + return sdkerrors.Wrap(ErrInvalidDuration, "both time and height are set") + } + if d.GetDuration() != nil && d.GetDuration().Seconds() < 0 { + return sdkerrors.Wrap(ErrInvalidDuration, "negative clock step") + } + return nil +} diff --git a/x/feegrant/types/expiration_test.go b/x/feegrant/types/expiration_test.go new file mode 100644 index 000000000000..60b1753bcbc1 --- /dev/null +++ b/x/feegrant/types/expiration_test.go @@ -0,0 +1,161 @@ +package types_test + +import ( + "testing" + "time" + + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestExpiresAt(t *testing.T) { + now := time.Now() + + cases := map[string]struct { + example types.ExpiresAt + valid bool + zero bool + before types.ExpiresAt + after types.ExpiresAt + }{ + "basic": { + example: types.ExpiresAtHeight(100), + valid: true, + before: types.ExpiresAtHeight(50), + after: types.ExpiresAtHeight(122), + }, + "zero": { + example: types.ExpiresAt{}, + zero: true, + valid: true, + before: types.ExpiresAtHeight(1), + }, + "match height": { + example: types.ExpiresAtHeight(1000), + valid: true, + before: types.ExpiresAtHeight(999), + after: types.ExpiresAtHeight(1000), + }, + "match time": { + example: types.ExpiresAtTime(now), + valid: true, + before: types.ExpiresAtTime(now.Add(-1 * time.Second)), + after: types.ExpiresAtTime(now.Add(1 * time.Second)), + }, + } + + for name, stc := range cases { + tc := stc // to make scopelint happy + t.Run(name, func(t *testing.T) { + err := tc.example.ValidateBasic() + assert.Equal(t, tc.zero, tc.example.Undefined()) + if !tc.valid { + require.Error(t, err) + return + } + require.NoError(t, err) + + if !tc.before.Undefined() { + assert.Equal(t, false, tc.example.IsExpired(tc.before.GetTime(), tc.before.GetHeight())) + } + if !tc.after.Undefined() { + assert.Equal(t, true, tc.example.IsExpired(tc.after.GetTime(), tc.after.GetHeight())) + } + }) + } +} + +func TestDurationValid(t *testing.T) { + now := time.Now() + + cases := map[string]struct { + period types.Duration + valid bool + compatible types.ExpiresAt + incompatible types.ExpiresAt + }{ + "basic height": { + period: types.BlockDuration(100), + valid: true, + compatible: types.ExpiresAtHeight(50), + incompatible: types.ExpiresAtTime(now), + }, + "basic time": { + period: types.ClockDuration(time.Hour), + valid: true, + compatible: types.ExpiresAtTime(now), + incompatible: types.ExpiresAtHeight(50), + }, + "zero": { + period: types.Duration{}, + valid: false, + }, + "negative clock": { + period: types.ClockDuration(-1 * time.Hour), + valid: false, + }, + } + + for name, stc := range cases { + tc := stc // to make scopelint happy + t.Run(name, func(t *testing.T) { + err := tc.period.ValidateBasic() + if !tc.valid { + require.Error(t, err) + return + } + require.NoError(t, err) + + assert.Equal(t, true, tc.compatible.IsCompatible(tc.period)) + assert.Equal(t, false, tc.incompatible.IsCompatible(tc.period)) + }) + } +} + +func TestDurationStep(t *testing.T) { + now := time.Now() + + cases := map[string]struct { + expires types.ExpiresAt + period types.Duration + valid bool + result types.ExpiresAt + }{ + "add height": { + expires: types.ExpiresAtHeight(789), + period: types.BlockDuration(100), + valid: true, + result: types.ExpiresAtHeight(889), + }, + "add time": { + expires: types.ExpiresAtTime(now), + period: types.ClockDuration(time.Hour), + valid: true, + result: types.ExpiresAtTime(now.Add(time.Hour)), + }, + "mismatch": { + expires: types.ExpiresAtHeight(789), + period: types.ClockDuration(time.Hour), + valid: false, + }, + } + + for name, stc := range cases { + tc := stc // to make scopelint happy + t.Run(name, func(t *testing.T) { + err := tc.period.ValidateBasic() + require.NoError(t, err) + err = tc.expires.ValidateBasic() + require.NoError(t, err) + + next, err := tc.expires.Step(tc.period) + if !tc.valid { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Equal(t, tc.result, next) + }) + } +} diff --git a/x/feegrant/types/feegrant.pb.go b/x/feegrant/types/feegrant.pb.go new file mode 100644 index 000000000000..2897bcc392d6 --- /dev/null +++ b/x/feegrant/types/feegrant.pb.go @@ -0,0 +1,1701 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/feegrant/v1beta1/feegrant.proto + +package types + +import ( + fmt "fmt" + types1 "github.com/cosmos/cosmos-sdk/codec/types" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" + _ "github.com/golang/protobuf/ptypes/duration" + _ "github.com/golang/protobuf/ptypes/timestamp" + _ "github.com/regen-network/cosmos-proto" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// BasicFeeAllowance implements FeeAllowance with a one-time grant of tokens +// that optionally expires. The delegatee can use up to SpendLimit to cover fees. +type BasicFeeAllowance struct { + // spend_limit specifies the maximum amount of tokens that can be spent + // by this allowance and will be updated as tokens are spent. If it is + // empty, there is no spend limit and any amount of coins can be spent. + SpendLimit github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,1,rep,name=spend_limit,json=spendLimit,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"spend_limit"` + // expiration specifies an optional time when this allowance expires + Expiration ExpiresAt `protobuf:"bytes,2,opt,name=expiration,proto3" json:"expiration"` +} + +func (m *BasicFeeAllowance) Reset() { *m = BasicFeeAllowance{} } +func (m *BasicFeeAllowance) String() string { return proto.CompactTextString(m) } +func (*BasicFeeAllowance) ProtoMessage() {} +func (*BasicFeeAllowance) Descriptor() ([]byte, []int) { + return fileDescriptor_7279582900c30aea, []int{0} +} +func (m *BasicFeeAllowance) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BasicFeeAllowance) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BasicFeeAllowance.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 *BasicFeeAllowance) XXX_Merge(src proto.Message) { + xxx_messageInfo_BasicFeeAllowance.Merge(m, src) +} +func (m *BasicFeeAllowance) XXX_Size() int { + return m.Size() +} +func (m *BasicFeeAllowance) XXX_DiscardUnknown() { + xxx_messageInfo_BasicFeeAllowance.DiscardUnknown(m) +} + +var xxx_messageInfo_BasicFeeAllowance proto.InternalMessageInfo + +func (m *BasicFeeAllowance) GetSpendLimit() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.SpendLimit + } + return nil +} + +func (m *BasicFeeAllowance) GetExpiration() ExpiresAt { + if m != nil { + return m.Expiration + } + return ExpiresAt{} +} + +// PeriodicFeeAllowance extends FeeAllowance to allow for both a maximum cap, +// as well as a limit per time period. +type PeriodicFeeAllowance struct { + // basic specifies a struct of `BasicFeeAllowance` + Basic BasicFeeAllowance `protobuf:"bytes,1,opt,name=basic,proto3" json:"basic"` + // period specifies the time duration in which period_spend_limit coins can + // be spent before that allowance is reset + Period Duration `protobuf:"bytes,2,opt,name=period,proto3" json:"period"` + // period_spend_limit specifies the maximum number of coins that can be spent + // in the period + PeriodSpendLimit github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,3,rep,name=period_spend_limit,json=periodSpendLimit,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"period_spend_limit"` + // period_can_spend is the number of coins left to be spent before the period_reset time + PeriodCanSpend github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,4,rep,name=period_can_spend,json=periodCanSpend,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"period_can_spend"` + // period_reset is the time at which this period resets and a new one begins, + // it is calculated from the start time of the first transaction after the + // last period ended + PeriodReset ExpiresAt `protobuf:"bytes,5,opt,name=period_reset,json=periodReset,proto3" json:"period_reset"` +} + +func (m *PeriodicFeeAllowance) Reset() { *m = PeriodicFeeAllowance{} } +func (m *PeriodicFeeAllowance) String() string { return proto.CompactTextString(m) } +func (*PeriodicFeeAllowance) ProtoMessage() {} +func (*PeriodicFeeAllowance) Descriptor() ([]byte, []int) { + return fileDescriptor_7279582900c30aea, []int{1} +} +func (m *PeriodicFeeAllowance) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PeriodicFeeAllowance) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PeriodicFeeAllowance.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 *PeriodicFeeAllowance) XXX_Merge(src proto.Message) { + xxx_messageInfo_PeriodicFeeAllowance.Merge(m, src) +} +func (m *PeriodicFeeAllowance) XXX_Size() int { + return m.Size() +} +func (m *PeriodicFeeAllowance) XXX_DiscardUnknown() { + xxx_messageInfo_PeriodicFeeAllowance.DiscardUnknown(m) +} + +var xxx_messageInfo_PeriodicFeeAllowance proto.InternalMessageInfo + +func (m *PeriodicFeeAllowance) GetBasic() BasicFeeAllowance { + if m != nil { + return m.Basic + } + return BasicFeeAllowance{} +} + +func (m *PeriodicFeeAllowance) GetPeriod() Duration { + if m != nil { + return m.Period + } + return Duration{} +} + +func (m *PeriodicFeeAllowance) GetPeriodSpendLimit() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.PeriodSpendLimit + } + return nil +} + +func (m *PeriodicFeeAllowance) GetPeriodCanSpend() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.PeriodCanSpend + } + return nil +} + +func (m *PeriodicFeeAllowance) GetPeriodReset() ExpiresAt { + if m != nil { + return m.PeriodReset + } + return ExpiresAt{} +} + +// Duration is a span of a clock time or number of blocks. +// This is designed to be added to an ExpiresAt struct. +type Duration struct { + // sum is the oneof that represents either duration or block + // + // Types that are valid to be assigned to Sum: + // *Duration_Duration + // *Duration_Blocks + Sum isDuration_Sum `protobuf_oneof:"sum"` +} + +func (m *Duration) Reset() { *m = Duration{} } +func (m *Duration) String() string { return proto.CompactTextString(m) } +func (*Duration) ProtoMessage() {} +func (*Duration) Descriptor() ([]byte, []int) { + return fileDescriptor_7279582900c30aea, []int{2} +} +func (m *Duration) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Duration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Duration.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 *Duration) XXX_Merge(src proto.Message) { + xxx_messageInfo_Duration.Merge(m, src) +} +func (m *Duration) XXX_Size() int { + return m.Size() +} +func (m *Duration) XXX_DiscardUnknown() { + xxx_messageInfo_Duration.DiscardUnknown(m) +} + +var xxx_messageInfo_Duration proto.InternalMessageInfo + +type isDuration_Sum interface { + isDuration_Sum() + MarshalTo([]byte) (int, error) + Size() int +} + +type Duration_Duration struct { + Duration *time.Duration `protobuf:"bytes,1,opt,name=duration,proto3,oneof,stdduration" json:"duration,omitempty"` +} +type Duration_Blocks struct { + Blocks uint64 `protobuf:"varint,2,opt,name=blocks,proto3,oneof" json:"blocks,omitempty"` +} + +func (*Duration_Duration) isDuration_Sum() {} +func (*Duration_Blocks) isDuration_Sum() {} + +func (m *Duration) GetSum() isDuration_Sum { + if m != nil { + return m.Sum + } + return nil +} + +func (m *Duration) GetDuration() *time.Duration { + if x, ok := m.GetSum().(*Duration_Duration); ok { + return x.Duration + } + return nil +} + +func (m *Duration) GetBlocks() uint64 { + if x, ok := m.GetSum().(*Duration_Blocks); ok { + return x.Blocks + } + return 0 +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*Duration) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*Duration_Duration)(nil), + (*Duration_Blocks)(nil), + } +} + +// ExpiresAt is a point in time where something expires. +// It may be *either* block time or block height +type ExpiresAt struct { + // sum is the oneof that represents either time or height + // + // Types that are valid to be assigned to Sum: + // *ExpiresAt_Time + // *ExpiresAt_Height + Sum isExpiresAt_Sum `protobuf_oneof:"sum"` +} + +func (m *ExpiresAt) Reset() { *m = ExpiresAt{} } +func (m *ExpiresAt) String() string { return proto.CompactTextString(m) } +func (*ExpiresAt) ProtoMessage() {} +func (*ExpiresAt) Descriptor() ([]byte, []int) { + return fileDescriptor_7279582900c30aea, []int{3} +} +func (m *ExpiresAt) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ExpiresAt) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ExpiresAt.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 *ExpiresAt) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExpiresAt.Merge(m, src) +} +func (m *ExpiresAt) XXX_Size() int { + return m.Size() +} +func (m *ExpiresAt) XXX_DiscardUnknown() { + xxx_messageInfo_ExpiresAt.DiscardUnknown(m) +} + +var xxx_messageInfo_ExpiresAt proto.InternalMessageInfo + +type isExpiresAt_Sum interface { + isExpiresAt_Sum() + MarshalTo([]byte) (int, error) + Size() int +} + +type ExpiresAt_Time struct { + Time *time.Time `protobuf:"bytes,1,opt,name=time,proto3,oneof,stdtime" json:"time,omitempty"` +} +type ExpiresAt_Height struct { + Height int64 `protobuf:"varint,2,opt,name=height,proto3,oneof" json:"height,omitempty"` +} + +func (*ExpiresAt_Time) isExpiresAt_Sum() {} +func (*ExpiresAt_Height) isExpiresAt_Sum() {} + +func (m *ExpiresAt) GetSum() isExpiresAt_Sum { + if m != nil { + return m.Sum + } + return nil +} + +func (m *ExpiresAt) GetTime() *time.Time { + if x, ok := m.GetSum().(*ExpiresAt_Time); ok { + return x.Time + } + return nil +} + +func (m *ExpiresAt) GetHeight() int64 { + if x, ok := m.GetSum().(*ExpiresAt_Height); ok { + return x.Height + } + return 0 +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*ExpiresAt) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*ExpiresAt_Time)(nil), + (*ExpiresAt_Height)(nil), + } +} + +// FeeAllowanceGrant is stored in the KVStore to record a grant with full context +type FeeAllowanceGrant struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` + Allowance *types1.Any `protobuf:"bytes,3,opt,name=allowance,proto3" json:"allowance,omitempty"` +} + +func (m *FeeAllowanceGrant) Reset() { *m = FeeAllowanceGrant{} } +func (m *FeeAllowanceGrant) String() string { return proto.CompactTextString(m) } +func (*FeeAllowanceGrant) ProtoMessage() {} +func (*FeeAllowanceGrant) Descriptor() ([]byte, []int) { + return fileDescriptor_7279582900c30aea, []int{4} +} +func (m *FeeAllowanceGrant) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *FeeAllowanceGrant) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_FeeAllowanceGrant.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 *FeeAllowanceGrant) XXX_Merge(src proto.Message) { + xxx_messageInfo_FeeAllowanceGrant.Merge(m, src) +} +func (m *FeeAllowanceGrant) XXX_Size() int { + return m.Size() +} +func (m *FeeAllowanceGrant) XXX_DiscardUnknown() { + xxx_messageInfo_FeeAllowanceGrant.DiscardUnknown(m) +} + +var xxx_messageInfo_FeeAllowanceGrant proto.InternalMessageInfo + +func (m *FeeAllowanceGrant) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *FeeAllowanceGrant) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *FeeAllowanceGrant) GetAllowance() *types1.Any { + if m != nil { + return m.Allowance + } + return nil +} + +func init() { + proto.RegisterType((*BasicFeeAllowance)(nil), "cosmos.feegrant.v1beta1.BasicFeeAllowance") + proto.RegisterType((*PeriodicFeeAllowance)(nil), "cosmos.feegrant.v1beta1.PeriodicFeeAllowance") + proto.RegisterType((*Duration)(nil), "cosmos.feegrant.v1beta1.Duration") + proto.RegisterType((*ExpiresAt)(nil), "cosmos.feegrant.v1beta1.ExpiresAt") + proto.RegisterType((*FeeAllowanceGrant)(nil), "cosmos.feegrant.v1beta1.FeeAllowanceGrant") +} + +func init() { + proto.RegisterFile("cosmos/feegrant/v1beta1/feegrant.proto", fileDescriptor_7279582900c30aea) +} + +var fileDescriptor_7279582900c30aea = []byte{ + // 599 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0x4f, 0x6e, 0xd3, 0x40, + 0x14, 0xc6, 0x6d, 0x9c, 0x96, 0x76, 0x02, 0x88, 0x8c, 0x22, 0xe1, 0x64, 0xe1, 0x94, 0x2c, 0x50, + 0x84, 0x14, 0x9b, 0x16, 0x89, 0x05, 0x12, 0x42, 0x71, 0x69, 0x1b, 0x04, 0x0b, 0x64, 0x58, 0xb1, + 0x89, 0x6c, 0x67, 0xea, 0x0c, 0xb5, 0x3d, 0x96, 0x67, 0x02, 0xcd, 0x25, 0x50, 0x97, 0x9c, 0x81, + 0x35, 0x87, 0xa8, 0x58, 0x55, 0xac, 0x58, 0xb5, 0x28, 0x39, 0x01, 0x37, 0x40, 0xf3, 0xc7, 0x4e, + 0x94, 0x10, 0x24, 0xa4, 0xae, 0xe2, 0x99, 0x79, 0xef, 0xfb, 0xbd, 0xf7, 0xbd, 0x99, 0x80, 0x07, + 0x21, 0xa1, 0x09, 0xa1, 0xce, 0x31, 0x42, 0x51, 0xee, 0xa7, 0xcc, 0xf9, 0xb8, 0x1b, 0x20, 0xe6, + 0xef, 0x96, 0x1b, 0x76, 0x96, 0x13, 0x46, 0xe0, 0x3d, 0x19, 0x67, 0x97, 0xdb, 0x2a, 0xae, 0x59, + 0x8f, 0x48, 0x44, 0x44, 0x8c, 0xc3, 0xbf, 0x64, 0x78, 0xb3, 0x11, 0x11, 0x12, 0xc5, 0xc8, 0x11, + 0xab, 0x60, 0x7c, 0xec, 0xf8, 0xe9, 0xa4, 0x38, 0x92, 0x4a, 0x03, 0x99, 0xa3, 0x64, 0xe5, 0x91, + 0xa5, 0x8a, 0x09, 0x7c, 0x8a, 0xca, 0x42, 0x42, 0x82, 0x53, 0x75, 0xde, 0x5a, 0x56, 0x65, 0x38, + 0x41, 0x94, 0xf9, 0x49, 0x56, 0x08, 0x2c, 0x07, 0x0c, 0xc7, 0xb9, 0xcf, 0x30, 0x51, 0x02, 0xed, + 0x4b, 0x1d, 0xd4, 0x5c, 0x9f, 0xe2, 0xf0, 0x10, 0xa1, 0x5e, 0x1c, 0x93, 0x4f, 0x7e, 0x1a, 0x22, + 0x18, 0x83, 0x2a, 0xcd, 0x50, 0x3a, 0x1c, 0xc4, 0x38, 0xc1, 0xcc, 0xd4, 0x77, 0x8c, 0x4e, 0x75, + 0xaf, 0x61, 0xab, 0xd2, 0x78, 0x31, 0x45, 0xb7, 0xf6, 0x3e, 0xc1, 0xa9, 0xfb, 0xe8, 0xfc, 0xb2, + 0xa5, 0x7d, 0xbd, 0x6a, 0x75, 0x22, 0xcc, 0x46, 0xe3, 0xc0, 0x0e, 0x49, 0xa2, 0xfa, 0x50, 0x3f, + 0x5d, 0x3a, 0x3c, 0x71, 0xd8, 0x24, 0x43, 0x54, 0x24, 0x50, 0x0f, 0x08, 0xfd, 0xd7, 0x5c, 0x1e, + 0xf6, 0x01, 0x40, 0xa7, 0x19, 0x96, 0x75, 0x99, 0x37, 0x76, 0xf4, 0x4e, 0x75, 0xaf, 0x6d, 0xaf, + 0xb1, 0xd7, 0x3e, 0xe0, 0xa1, 0x88, 0xf6, 0x98, 0x5b, 0xe1, 0x54, 0x6f, 0x21, 0xf7, 0x69, 0xed, + 0xc7, 0xb7, 0xee, 0xed, 0xc5, 0x4e, 0x5e, 0xb6, 0x7f, 0x1b, 0xa0, 0xfe, 0x06, 0xe5, 0x98, 0x0c, + 0x97, 0x7a, 0x3c, 0x04, 0x1b, 0x01, 0x6f, 0xdc, 0xd4, 0x05, 0xf0, 0xe1, 0x5a, 0xe0, 0x8a, 0x3d, + 0x0a, 0x2c, 0xd3, 0xe1, 0x73, 0xb0, 0x99, 0x09, 0x7d, 0x55, 0xf9, 0xfd, 0xb5, 0x42, 0x2f, 0x94, + 0xf5, 0x2a, 0x5f, 0xa5, 0xc1, 0x09, 0x80, 0xf2, 0x6b, 0xb0, 0xe8, 0xb9, 0x71, 0xfd, 0x9e, 0xdf, + 0x95, 0x98, 0xb7, 0x73, 0xe7, 0xc7, 0x40, 0xed, 0x0d, 0x42, 0x3f, 0x95, 0x78, 0xb3, 0x72, 0xfd, + 0xe0, 0x3b, 0x12, 0xb2, 0xef, 0xa7, 0x82, 0x0d, 0x5f, 0x81, 0x5b, 0x0a, 0x9b, 0x23, 0x8a, 0x98, + 0xb9, 0xf1, 0x9f, 0x23, 0xaf, 0xca, 0x6c, 0x8f, 0x27, 0xff, 0x6d, 0xe6, 0x1f, 0xc0, 0x56, 0xe1, + 0x35, 0x7c, 0x06, 0xb6, 0x8a, 0x2b, 0xaf, 0x26, 0xdd, 0xb0, 0xe5, 0x9b, 0xb0, 0x8b, 0x37, 0xb1, + 0x30, 0x98, 0x2f, 0x57, 0x2d, 0xbd, 0xaf, 0x79, 0x65, 0x0a, 0x34, 0xc1, 0x66, 0x10, 0x93, 0xf0, + 0x84, 0x8a, 0xe9, 0x56, 0xfa, 0x9a, 0xa7, 0xd6, 0xee, 0x06, 0x30, 0xe8, 0x38, 0x69, 0x0f, 0xc1, + 0x76, 0x59, 0x1e, 0x7c, 0x02, 0x2a, 0xfc, 0x01, 0x2a, 0x50, 0x73, 0x05, 0xf4, 0xae, 0x78, 0x9d, + 0x6e, 0xe5, 0x4c, 0x92, 0x44, 0x3c, 0xa7, 0x8c, 0x10, 0x8e, 0x46, 0x4c, 0x50, 0x0c, 0x4e, 0x91, + 0xeb, 0x82, 0xf2, 0x59, 0x07, 0xb5, 0xc5, 0x1e, 0x8f, 0xb8, 0x3f, 0xd0, 0x04, 0x37, 0x85, 0x51, + 0x28, 0x17, 0xc4, 0x6d, 0xaf, 0x58, 0xce, 0x4f, 0x90, 0x50, 0x2c, 0x4f, 0x10, 0x3c, 0x00, 0xdb, + 0x7e, 0xa1, 0x62, 0x1a, 0xa2, 0xce, 0xfa, 0x4a, 0x9d, 0xbd, 0x74, 0xe2, 0xd6, 0xbe, 0x2f, 0xfb, + 0xea, 0xcd, 0x33, 0xdd, 0xa3, 0xf3, 0xa9, 0xa5, 0x5f, 0x4c, 0x2d, 0xfd, 0xd7, 0xd4, 0xd2, 0xcf, + 0x66, 0x96, 0x76, 0x31, 0xb3, 0xb4, 0x9f, 0x33, 0x4b, 0x7b, 0xdf, 0xfd, 0xe7, 0xb5, 0x38, 0x9d, + 0xff, 0xaf, 0x8a, 0x1b, 0x12, 0x6c, 0x0a, 0xe8, 0xe3, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x74, + 0x27, 0xe6, 0x00, 0x77, 0x05, 0x00, 0x00, +} + +func (m *BasicFeeAllowance) 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 *BasicFeeAllowance) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BasicFeeAllowance) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Expiration.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintFeegrant(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.SpendLimit) > 0 { + for iNdEx := len(m.SpendLimit) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.SpendLimit[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintFeegrant(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *PeriodicFeeAllowance) 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 *PeriodicFeeAllowance) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PeriodicFeeAllowance) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.PeriodReset.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintFeegrant(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + if len(m.PeriodCanSpend) > 0 { + for iNdEx := len(m.PeriodCanSpend) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.PeriodCanSpend[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintFeegrant(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if len(m.PeriodSpendLimit) > 0 { + for iNdEx := len(m.PeriodSpendLimit) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.PeriodSpendLimit[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintFeegrant(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + { + size, err := m.Period.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintFeegrant(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + { + size, err := m.Basic.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintFeegrant(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *Duration) 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 *Duration) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Duration) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Sum != nil { + { + size := m.Sum.Size() + i -= size + if _, err := m.Sum.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *Duration_Duration) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Duration_Duration) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Duration != nil { + n5, err5 := github_com_gogo_protobuf_types.StdDurationMarshalTo(*m.Duration, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(*m.Duration):]) + if err5 != nil { + return 0, err5 + } + i -= n5 + i = encodeVarintFeegrant(dAtA, i, uint64(n5)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *Duration_Blocks) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Duration_Blocks) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + i = encodeVarintFeegrant(dAtA, i, uint64(m.Blocks)) + i-- + dAtA[i] = 0x10 + return len(dAtA) - i, nil +} +func (m *ExpiresAt) 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 *ExpiresAt) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExpiresAt) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Sum != nil { + { + size := m.Sum.Size() + i -= size + if _, err := m.Sum.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *ExpiresAt_Time) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExpiresAt_Time) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Time != nil { + n6, err6 := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(*m.Time):]) + if err6 != nil { + return 0, err6 + } + i -= n6 + i = encodeVarintFeegrant(dAtA, i, uint64(n6)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *ExpiresAt_Height) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExpiresAt_Height) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + i = encodeVarintFeegrant(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x10 + return len(dAtA) - i, nil +} +func (m *FeeAllowanceGrant) 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 *FeeAllowanceGrant) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *FeeAllowanceGrant) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Allowance != nil { + { + size, err := m.Allowance.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintFeegrant(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintFeegrant(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintFeegrant(dAtA, i, uint64(len(m.Granter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintFeegrant(dAtA []byte, offset int, v uint64) int { + offset -= sovFeegrant(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *BasicFeeAllowance) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.SpendLimit) > 0 { + for _, e := range m.SpendLimit { + l = e.Size() + n += 1 + l + sovFeegrant(uint64(l)) + } + } + l = m.Expiration.Size() + n += 1 + l + sovFeegrant(uint64(l)) + return n +} + +func (m *PeriodicFeeAllowance) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Basic.Size() + n += 1 + l + sovFeegrant(uint64(l)) + l = m.Period.Size() + n += 1 + l + sovFeegrant(uint64(l)) + if len(m.PeriodSpendLimit) > 0 { + for _, e := range m.PeriodSpendLimit { + l = e.Size() + n += 1 + l + sovFeegrant(uint64(l)) + } + } + if len(m.PeriodCanSpend) > 0 { + for _, e := range m.PeriodCanSpend { + l = e.Size() + n += 1 + l + sovFeegrant(uint64(l)) + } + } + l = m.PeriodReset.Size() + n += 1 + l + sovFeegrant(uint64(l)) + return n +} + +func (m *Duration) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Sum != nil { + n += m.Sum.Size() + } + return n +} + +func (m *Duration_Duration) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Duration != nil { + l = github_com_gogo_protobuf_types.SizeOfStdDuration(*m.Duration) + n += 1 + l + sovFeegrant(uint64(l)) + } + return n +} +func (m *Duration_Blocks) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += 1 + sovFeegrant(uint64(m.Blocks)) + return n +} +func (m *ExpiresAt) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Sum != nil { + n += m.Sum.Size() + } + return n +} + +func (m *ExpiresAt_Time) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Time != nil { + l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.Time) + n += 1 + l + sovFeegrant(uint64(l)) + } + return n +} +func (m *ExpiresAt_Height) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += 1 + sovFeegrant(uint64(m.Height)) + return n +} +func (m *FeeAllowanceGrant) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovFeegrant(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovFeegrant(uint64(l)) + } + if m.Allowance != nil { + l = m.Allowance.Size() + n += 1 + l + sovFeegrant(uint64(l)) + } + return n +} + +func sovFeegrant(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozFeegrant(x uint64) (n int) { + return sovFeegrant(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *BasicFeeAllowance) 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 ErrIntOverflowFeegrant + } + 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: BasicFeeAllowance: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BasicFeeAllowance: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SpendLimit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SpendLimit = append(m.SpendLimit, types.Coin{}) + if err := m.SpendLimit[len(m.SpendLimit)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiration", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Expiration.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipFeegrant(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthFeegrant + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PeriodicFeeAllowance) 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 ErrIntOverflowFeegrant + } + 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: PeriodicFeeAllowance: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PeriodicFeeAllowance: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Basic", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Basic.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Period", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Period.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PeriodSpendLimit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PeriodSpendLimit = append(m.PeriodSpendLimit, types.Coin{}) + if err := m.PeriodSpendLimit[len(m.PeriodSpendLimit)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PeriodCanSpend", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PeriodCanSpend = append(m.PeriodCanSpend, types.Coin{}) + if err := m.PeriodCanSpend[len(m.PeriodCanSpend)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PeriodReset", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.PeriodReset.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipFeegrant(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthFeegrant + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Duration) 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 ErrIntOverflowFeegrant + } + 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: Duration: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Duration: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Duration", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := new(time.Duration) + if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(v, dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Duration_Duration{v} + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Blocks", wireType) + } + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Sum = &Duration_Blocks{v} + default: + iNdEx = preIndex + skippy, err := skipFeegrant(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthFeegrant + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ExpiresAt) 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 ErrIntOverflowFeegrant + } + 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: ExpiresAt: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExpiresAt: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := new(time.Time) + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(v, dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &ExpiresAt_Time{v} + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + var v int64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Sum = &ExpiresAt_Height{v} + default: + iNdEx = preIndex + skippy, err := skipFeegrant(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthFeegrant + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *FeeAllowanceGrant) 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 ErrIntOverflowFeegrant + } + 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: FeeAllowanceGrant: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: FeeAllowanceGrant: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Allowance", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Allowance == nil { + m.Allowance = &types1.Any{} + } + if err := m.Allowance.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipFeegrant(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthFeegrant + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipFeegrant(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowFeegrant + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowFeegrant + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowFeegrant + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthFeegrant + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupFeegrant + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthFeegrant + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthFeegrant = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowFeegrant = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupFeegrant = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/feegrant/types/fees.go b/x/feegrant/types/fees.go new file mode 100644 index 000000000000..cc526628f5f9 --- /dev/null +++ b/x/feegrant/types/fees.go @@ -0,0 +1,32 @@ +package types + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// FeeAllowance implementations are tied to a given fee delegator and delegatee, +// and are used to enforce fee grant limits. +type FeeAllowanceI interface { + // Accept can use fee payment requested as well as timestamp/height of the current block + // to determine whether or not to process this. This is checked in + // Keeper.UseGrantedFees and the return values should match how it is handled there. + // + // If it returns an error, the fee payment is rejected, otherwise it is accepted. + // The FeeAllowance implementation is expected to update it's internal state + // and will be saved again after an acceptance. + // + // If remove is true (regardless of the error), the FeeAllowance will be deleted from storage + // (eg. when it is used up). (See call to RevokeFeeAllowance in Keeper.UseGrantedFees) + Accept(fee sdk.Coins, blockTime time.Time, blockHeight int64) (remove bool, err error) + + // If we export fee allowances the timing info will be quite off (eg. go from height 100000 to 0) + // This callback allows the fee-allowance to change it's state and return a copy that is adjusted + // given the time and height of the actual dump (may safely return self if no changes needed) + PrepareForExport(dumpTime time.Time, dumpHeight int64) FeeAllowanceI + + // ValidateBasic should evaluate this FeeAllowance for internal consistency. + // Don't allow negative amounts, or negative periods for example. + ValidateBasic() error +} diff --git a/x/feegrant/types/genesis.go b/x/feegrant/types/genesis.go new file mode 100644 index 000000000000..57ade9b43de2 --- /dev/null +++ b/x/feegrant/types/genesis.go @@ -0,0 +1,40 @@ +package types + +import "github.com/cosmos/cosmos-sdk/codec/types" + +var _ types.UnpackInterfacesMessage = GenesisState{} + +// NewGenesisState creates new GenesisState object +func NewGenesisState(entries []FeeAllowanceGrant) *GenesisState { + return &GenesisState{ + FeeAllowances: entries, + } +} + +// ValidateGenesis ensures all grants in the genesis state are valid +func ValidateGenesis(data GenesisState) error { + for _, f := range data.FeeAllowances { + err := f.GetFeeGrant().ValidateBasic() + if err != nil { + return err + } + } + return nil +} + +// DefaultGenesisState returns default state for feegrant module. +func DefaultGenesisState() *GenesisState { + return &GenesisState{} +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (data GenesisState) UnpackInterfaces(unpacker types.AnyUnpacker) error { + for _, f := range data.FeeAllowances { + err := f.UnpackInterfaces(unpacker) + if err != nil { + return err + } + } + + return nil +} diff --git a/x/feegrant/types/genesis.pb.go b/x/feegrant/types/genesis.pb.go new file mode 100644 index 000000000000..499f57d626d6 --- /dev/null +++ b/x/feegrant/types/genesis.pb.go @@ -0,0 +1,333 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/feegrant/v1beta1/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GenesisState contains a set of fee allowances, persisted from the store +type GenesisState struct { + FeeAllowances []FeeAllowanceGrant `protobuf:"bytes,1,rep,name=fee_allowances,json=feeAllowances,proto3" json:"fee_allowances"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_ac719d2d0954d1bf, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.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 *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetFeeAllowances() []FeeAllowanceGrant { + if m != nil { + return m.FeeAllowances + } + return nil +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "cosmos.feegrant.v1beta1.GenesisState") +} + +func init() { + proto.RegisterFile("cosmos/feegrant/v1beta1/genesis.proto", fileDescriptor_ac719d2d0954d1bf) +} + +var fileDescriptor_ac719d2d0954d1bf = []byte{ + // 221 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4d, 0xce, 0x2f, 0xce, + 0xcd, 0x2f, 0xd6, 0x4f, 0x4b, 0x4d, 0x4d, 0x2f, 0x4a, 0xcc, 0x2b, 0xd1, 0x2f, 0x33, 0x4c, 0x4a, + 0x2d, 0x49, 0x34, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, + 0xc9, 0x17, 0x12, 0x87, 0x28, 0xd3, 0x83, 0x29, 0xd3, 0x83, 0x2a, 0x93, 0x12, 0x49, 0xcf, 0x4f, + 0xcf, 0x07, 0xab, 0xd1, 0x07, 0xb1, 0x20, 0xca, 0xa5, 0xd4, 0x70, 0x99, 0x0a, 0xd7, 0x0f, 0x56, + 0xa7, 0x94, 0xce, 0xc5, 0xe3, 0x0e, 0xb1, 0x27, 0xb8, 0x24, 0xb1, 0x24, 0x55, 0x28, 0x9c, 0x8b, + 0x2f, 0x2d, 0x35, 0x35, 0x3e, 0x31, 0x27, 0x27, 0xbf, 0x3c, 0x31, 0x2f, 0x39, 0xb5, 0x58, 0x82, + 0x51, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x4b, 0x0f, 0x87, 0xfd, 0x7a, 0x6e, 0xa9, 0xa9, 0x8e, 0x30, + 0xd5, 0xee, 0x20, 0x19, 0x27, 0x96, 0x13, 0xf7, 0xe4, 0x19, 0x82, 0x78, 0xd3, 0x90, 0x24, 0x8a, + 0x9d, 0xdc, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, + 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x37, 0x3d, 0xb3, + 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0x1f, 0xea, 0x6a, 0x08, 0xa5, 0x5b, 0x9c, 0x92, + 0xad, 0x5f, 0x81, 0xf0, 0x42, 0x49, 0x65, 0x41, 0x6a, 0x71, 0x12, 0x1b, 0xd8, 0xe1, 0xc6, 0x80, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xaf, 0x53, 0x6e, 0xc5, 0x38, 0x01, 0x00, 0x00, +} + +func (m *GenesisState) 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 *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.FeeAllowances) > 0 { + for iNdEx := len(m.FeeAllowances) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.FeeAllowances[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.FeeAllowances) > 0 { + for _, e := range m.FeeAllowances { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) 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 ErrIntOverflowGenesis + } + 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: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FeeAllowances", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FeeAllowances = append(m.FeeAllowances, FeeAllowanceGrant{}) + if err := m.FeeAllowances[len(m.FeeAllowances)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/feegrant/types/grant.go b/x/feegrant/types/grant.go new file mode 100644 index 000000000000..ca2c93d9efb2 --- /dev/null +++ b/x/feegrant/types/grant.go @@ -0,0 +1,92 @@ +package types + +import ( + "time" + + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + proto "github.com/gogo/protobuf/proto" +) + +var ( + _ types.UnpackInterfacesMessage = &FeeAllowanceGrant{} +) + +// NewFeeAllowanceGrant creates a new FeeAllowanceGrant. +//nolint:interfacer +func NewFeeAllowanceGrant(granter, grantee sdk.AccAddress, feeAllowance FeeAllowanceI) (FeeAllowanceGrant, error) { + msg, ok := feeAllowance.(proto.Message) + if !ok { + return FeeAllowanceGrant{}, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", feeAllowance) + } + + any, err := types.NewAnyWithValue(msg) + if err != nil { + return FeeAllowanceGrant{}, err + } + + return FeeAllowanceGrant{ + Granter: granter.String(), + Grantee: grantee.String(), + Allowance: any, + }, nil +} + +// ValidateBasic performs basic validation on +// FeeAllowanceGrant +func (a FeeAllowanceGrant) ValidateBasic() error { + if a.Granter == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing granter address") + } + if a.Grantee == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing grantee address") + } + if a.Grantee == a.Granter { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "cannot self-grant fee authorization") + } + + return a.GetFeeGrant().ValidateBasic() +} + +// GetFeeGrant unpacks allowance +func (a FeeAllowanceGrant) GetFeeGrant() FeeAllowanceI { + allowance, ok := a.Allowance.GetCachedValue().(FeeAllowanceI) + if !ok { + return nil + } + + return allowance +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (a FeeAllowanceGrant) UnpackInterfaces(unpacker types.AnyUnpacker) error { + var allowance FeeAllowanceI + return unpacker.UnpackAny(a.Allowance, &allowance) +} + +// PrepareForExport will make all needed changes to the allowance to prepare to be +// re-imported at height 0, and return a copy of this grant. +func (a FeeAllowanceGrant) PrepareForExport(dumpTime time.Time, dumpHeight int64) FeeAllowanceGrant { + feegrant := a.GetFeeGrant().PrepareForExport(dumpTime, dumpHeight) + if feegrant == nil { + return FeeAllowanceGrant{} + } + + granter, err := sdk.AccAddressFromBech32(a.Granter) + if err != nil { + return FeeAllowanceGrant{} + } + + grantee, err := sdk.AccAddressFromBech32(a.Grantee) + if err != nil { + return FeeAllowanceGrant{} + } + + grant, err := NewFeeAllowanceGrant(granter, grantee, feegrant) + if err != nil { + return FeeAllowanceGrant{} + } + + return grant +} diff --git a/x/feegrant/types/grant_test.go b/x/feegrant/types/grant_test.go new file mode 100644 index 000000000000..a4819b102cb2 --- /dev/null +++ b/x/feegrant/types/grant_test.go @@ -0,0 +1,99 @@ +package types_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGrant(t *testing.T) { + app := simapp.Setup(false) + addr, err := sdk.AccAddressFromBech32("cosmos1qk93t4j0yyzgqgt6k5qf8deh8fq6smpn3ntu3x") + require.NoError(t, err) + addr2, err := sdk.AccAddressFromBech32("cosmos1p9qh4ldfd6n0qehujsal4k7g0e37kel90rc4ts") + require.NoError(t, err) + atom := sdk.NewCoins(sdk.NewInt64Coin("atom", 555)) + + goodGrant, err := types.NewFeeAllowanceGrant(addr2, addr, &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }) + require.NoError(t, err) + + noGranteeGrant, err := types.NewFeeAllowanceGrant(addr2, nil, &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }) + require.NoError(t, err) + + noGranterGrant, err := types.NewFeeAllowanceGrant(nil, addr, &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }) + require.NoError(t, err) + + selfGrant, err := types.NewFeeAllowanceGrant(addr2, addr2, &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }) + require.NoError(t, err) + + badAllowanceGrant, err := types.NewFeeAllowanceGrant(addr2, addr, &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(-1), + }) + require.NoError(t, err) + + cdc := app.AppCodec() + // RegisterLegacyAminoCodec(cdc) + + cases := map[string]struct { + grant types.FeeAllowanceGrant + valid bool + }{ + "good": { + grant: goodGrant, + valid: true, + }, + "no grantee": { + grant: noGranteeGrant, + }, + "no granter": { + grant: noGranterGrant, + }, + "self-grant": { + grant: selfGrant, + }, + "bad allowance": { + grant: badAllowanceGrant, + }, + } + + for name, tc := range cases { + tc := tc + t.Run(name, func(t *testing.T) { + err := tc.grant.ValidateBasic() + if !tc.valid { + require.Error(t, err) + return + } + require.NoError(t, err) + + // if it is valid, let's try to serialize, deserialize, and make sure it matches + bz, err := cdc.MarshalBinaryBare(&tc.grant) + require.NoError(t, err) + var loaded types.FeeAllowanceGrant + err = cdc.UnmarshalBinaryBare(bz, &loaded) + require.NoError(t, err) + + err = loaded.ValidateBasic() + require.NoError(t, err) + + assert.Equal(t, tc.grant, loaded) + }) + } +} diff --git a/x/feegrant/types/key.go b/x/feegrant/types/key.go new file mode 100644 index 000000000000..e30427b136b4 --- /dev/null +++ b/x/feegrant/types/key.go @@ -0,0 +1,35 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + // ModuleName is the module name constant used in many places + ModuleName = "feegrant" + + // StoreKey is the store key string for supply + StoreKey = ModuleName + + // RouterKey is the message route for supply + RouterKey = ModuleName + + // QuerierRoute is the querier route for supply + QuerierRoute = ModuleName +) + +var ( + // FeeAllowanceKeyPrefix is the set of the kvstore for fee allowance data + FeeAllowanceKeyPrefix = []byte{0x00} +) + +// FeeAllowanceKey is the canonical key to store a grant from granter to grantee +// We store by grantee first to allow searching by everyone who granted to you +func FeeAllowanceKey(granter sdk.AccAddress, grantee sdk.AccAddress) []byte { + return append(append(FeeAllowanceKeyPrefix, grantee.Bytes()...), granter.Bytes()...) +} + +// FeeAllowancePrefixByGrantee returns a prefix to scan for all grants to this given address. +func FeeAllowancePrefixByGrantee(grantee sdk.AccAddress) []byte { + return append(FeeAllowanceKeyPrefix, grantee.Bytes()...) +} diff --git a/x/feegrant/types/msgs.go b/x/feegrant/types/msgs.go new file mode 100644 index 000000000000..5a25016f87e0 --- /dev/null +++ b/x/feegrant/types/msgs.go @@ -0,0 +1,101 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/gogo/protobuf/proto" +) + +var ( + _, _ sdk.MsgRequest = &MsgGrantFeeAllowance{}, &MsgRevokeFeeAllowance{} + _ types.UnpackInterfacesMessage = &MsgGrantFeeAllowance{} +) + +// feegrant message types +const ( + TypeMsgGrantFeeAllowance = "grant_fee_allowance" + TypeMsgRevokeFeeAllowance = "revoke_fee_allowance" +) + +// NewMsgGrantFeeAllowance creates a new MsgGrantFeeAllowance. +//nolint:interfacer +func NewMsgGrantFeeAllowance(feeAllowance FeeAllowanceI, granter, grantee sdk.AccAddress) (*MsgGrantFeeAllowance, error) { + msg, ok := feeAllowance.(proto.Message) + if !ok { + return nil, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", msg) + } + any, err := types.NewAnyWithValue(msg) + if err != nil { + return nil, err + } + + return &MsgGrantFeeAllowance{ + Granter: granter.String(), + Grantee: grantee.String(), + Allowance: any, + }, nil +} + +// ValidateBasic implements the sdk.Msg interface. +func (msg MsgGrantFeeAllowance) ValidateBasic() error { + if msg.Granter == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing granter address") + } + if msg.Grantee == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing grantee address") + } + if msg.Grantee == msg.Granter { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "cannot self-grant fee authorization") + } + + return msg.GetFeeAllowanceI().ValidateBasic() +} + +func (msg MsgGrantFeeAllowance) GetSigners() []sdk.AccAddress { + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + panic(err) + } + return []sdk.AccAddress{granter} +} + +// GetFeeAllowanceI returns unpacked FeeAllowance +func (msg MsgGrantFeeAllowance) GetFeeAllowanceI() FeeAllowanceI { + allowance, ok := msg.Allowance.GetCachedValue().(FeeAllowanceI) + if !ok { + return nil + } + + return allowance +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (msg MsgGrantFeeAllowance) UnpackInterfaces(unpacker types.AnyUnpacker) error { + var allowance FeeAllowanceI + return unpacker.UnpackAny(msg.Allowance, &allowance) +} + +//nolint:interfacer +func NewMsgRevokeFeeAllowance(granter sdk.AccAddress, grantee sdk.AccAddress) MsgRevokeFeeAllowance { + return MsgRevokeFeeAllowance{Granter: granter.String(), Grantee: grantee.String()} +} + +func (msg MsgRevokeFeeAllowance) ValidateBasic() error { + if msg.Granter == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing granter address") + } + if msg.Grantee == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing grantee address") + } + + return nil +} + +func (msg MsgRevokeFeeAllowance) GetSigners() []sdk.AccAddress { + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + panic(err) + } + return []sdk.AccAddress{granter} +} diff --git a/x/feegrant/types/periodic_fee.go b/x/feegrant/types/periodic_fee.go new file mode 100644 index 000000000000..61c9ba2ffe2d --- /dev/null +++ b/x/feegrant/types/periodic_fee.go @@ -0,0 +1,120 @@ +package types + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +var _ FeeAllowanceI = (*PeriodicFeeAllowance)(nil) + +// Accept can use fee payment requested as well as timestamp/height of the current block +// to determine whether or not to process this. This is checked in +// Keeper.UseGrantedFees and the return values should match how it is handled there. +// +// If it returns an error, the fee payment is rejected, otherwise it is accepted. +// The FeeAllowance implementation is expected to update it's internal state +// and will be saved again after an acceptance. +// +// If remove is true (regardless of the error), the FeeAllowance will be deleted from storage +// (eg. when it is used up). (See call to RevokeFeeAllowance in Keeper.UseGrantedFees) +func (a *PeriodicFeeAllowance) Accept(fee sdk.Coins, blockTime time.Time, blockHeight int64) (bool, error) { + if a.Basic.Expiration.IsExpired(&blockTime, blockHeight) { + return true, sdkerrors.Wrap(ErrFeeLimitExpired, "absolute limit") + } + + a.tryResetPeriod(blockTime, blockHeight) + + // deduct from both the current period and the max amount + var isNeg bool + a.PeriodCanSpend, isNeg = a.PeriodCanSpend.SafeSub(fee) + if isNeg { + return false, sdkerrors.Wrap(ErrFeeLimitExceeded, "period limit") + } + + if a.Basic.SpendLimit != nil { + a.Basic.SpendLimit, isNeg = a.Basic.SpendLimit.SafeSub(fee) + if isNeg { + return false, sdkerrors.Wrap(ErrFeeLimitExceeded, "absolute limit") + } + + return a.Basic.SpendLimit.IsZero(), nil + } + + return false, nil +} + +// tryResetPeriod will check if the PeriodReset has been hit. If not, it is a no-op. +// If we hit the reset period, it will top up the PeriodCanSpend amount to +// min(PeriodicSpendLimit, a.Basic.SpendLimit) so it is never more than the maximum allowed. +// It will also update the PeriodReset. If we are within one Period, it will update from the +// last PeriodReset (eg. if you always do one tx per day, it will always reset the same time) +// If we are more then one period out (eg. no activity in a week), reset is one Period from the execution of this method +func (a *PeriodicFeeAllowance) tryResetPeriod(blockTime time.Time, blockHeight int64) { + if !a.PeriodReset.Undefined() && !a.PeriodReset.IsExpired(&blockTime, blockHeight) { + return + } + // set CanSpend to the lesser of PeriodSpendLimit and the TotalLimit + if _, isNeg := a.Basic.SpendLimit.SafeSub(a.PeriodSpendLimit); isNeg { + a.PeriodCanSpend = a.Basic.SpendLimit + } else { + a.PeriodCanSpend = a.PeriodSpendLimit + } + + // If we are within the period, step from expiration (eg. if you always do one tx per day, it will always reset the same time) + // If we are more then one period out (eg. no activity in a week), reset is one period from this time + a.PeriodReset = a.PeriodReset.MustStep(a.Period) + if a.PeriodReset.IsExpired(&blockTime, blockHeight) { + a.PeriodReset = a.PeriodReset.FastForward(blockTime, blockHeight).MustStep(a.Period) + } +} + +// PrepareForExport will adjust the expiration based on export time. In particular, +// it will subtract the dumpHeight from any height-based expiration to ensure that +// the elapsed number of blocks this allowance is valid for is fixed. +// (For PeriodReset and Basic.Expiration) +func (a *PeriodicFeeAllowance) PrepareForExport(dumpTime time.Time, dumpHeight int64) FeeAllowanceI { + return &PeriodicFeeAllowance{ + Basic: BasicFeeAllowance{ + SpendLimit: a.Basic.SpendLimit, + Expiration: a.Basic.Expiration.PrepareForExport(dumpTime, dumpHeight), + }, + PeriodSpendLimit: a.PeriodSpendLimit, + PeriodCanSpend: a.PeriodCanSpend, + Period: a.Period, + PeriodReset: a.PeriodReset.PrepareForExport(dumpTime, dumpHeight), + } +} + +// ValidateBasic implements FeeAllowance and enforces basic sanity checks +func (a PeriodicFeeAllowance) ValidateBasic() error { + if err := a.Basic.ValidateBasic(); err != nil { + return err + } + + if !a.PeriodSpendLimit.IsValid() { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "spend amount is invalid: %s", a.PeriodSpendLimit) + } + if !a.PeriodSpendLimit.IsAllPositive() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "spend limit must be positive") + } + if !a.PeriodCanSpend.IsValid() { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "can spend amount is invalid: %s", a.PeriodCanSpend) + } + // We allow 0 for CanSpend + if a.PeriodCanSpend.IsAnyNegative() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "can spend must not be negative") + } + + // ensure PeriodSpendLimit can be subtracted from total (same coin types) + if a.Basic.SpendLimit != nil && !a.PeriodSpendLimit.DenomsSubsetOf(a.Basic.SpendLimit) { + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "period spend limit has different currency than basic spend limit") + } + + // check times + if err := a.Period.ValidateBasic(); err != nil { + return err + } + return a.PeriodReset.ValidateBasic() +} diff --git a/x/feegrant/types/periodic_fee_test.go b/x/feegrant/types/periodic_fee_test.go new file mode 100644 index 000000000000..cc54f4080878 --- /dev/null +++ b/x/feegrant/types/periodic_fee_test.go @@ -0,0 +1,205 @@ +package types_test + +import ( + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestPeriodicFeeValidAllow(t *testing.T) { + atom := sdk.NewCoins(sdk.NewInt64Coin("atom", 555)) + smallAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 43)) + leftAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 512)) + oneAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 1)) + eth := sdk.NewCoins(sdk.NewInt64Coin("eth", 1)) + + cases := map[string]struct { + allow types.PeriodicFeeAllowance + // all other checks are ignored if valid=false + fee sdk.Coins + blockTime time.Time + blockHeight int64 + valid bool + accept bool + remove bool + remains sdk.Coins + remainsPeriod sdk.Coins + periodReset types.ExpiresAt + }{ + "empty": { + allow: types.PeriodicFeeAllowance{}, + valid: false, + }, + "only basic": { + allow: types.PeriodicFeeAllowance{ + Basic: types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + }, + valid: false, + }, + "empty basic": { + allow: types.PeriodicFeeAllowance{ + Period: types.BlockDuration(10), + PeriodSpendLimit: smallAtom, + PeriodReset: types.ExpiresAtHeight(70), + }, + blockHeight: 75, + valid: true, + accept: true, + remove: false, + periodReset: types.ExpiresAtHeight(80), + }, + "mismatched currencies": { + allow: types.PeriodicFeeAllowance{ + Basic: types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + Period: types.BlockDuration(10), + PeriodSpendLimit: eth, + }, + valid: false, + }, + "first time": { + allow: types.PeriodicFeeAllowance{ + Basic: types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + Period: types.BlockDuration(10), + PeriodSpendLimit: smallAtom, + }, + valid: true, + fee: smallAtom, + blockHeight: 75, + accept: true, + remove: false, + remainsPeriod: nil, + remains: leftAtom, + periodReset: types.ExpiresAtHeight(85), + }, + "same period": { + allow: types.PeriodicFeeAllowance{ + Basic: types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + Period: types.BlockDuration(10), + PeriodReset: types.ExpiresAtHeight(80), + PeriodSpendLimit: leftAtom, + PeriodCanSpend: smallAtom, + }, + valid: true, + fee: smallAtom, + blockHeight: 75, + accept: true, + remove: false, + remainsPeriod: nil, + remains: leftAtom, + periodReset: types.ExpiresAtHeight(80), + }, + "step one period": { + allow: types.PeriodicFeeAllowance{ + Basic: types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + Period: types.BlockDuration(10), + PeriodReset: types.ExpiresAtHeight(70), + PeriodSpendLimit: leftAtom, + }, + valid: true, + fee: leftAtom, + blockHeight: 75, + accept: true, + remove: false, + remainsPeriod: nil, + remains: smallAtom, + periodReset: types.ExpiresAtHeight(80), // one step from last reset, not now + }, + "step limited by global allowance": { + allow: types.PeriodicFeeAllowance{ + Basic: types.BasicFeeAllowance{ + SpendLimit: smallAtom, + Expiration: types.ExpiresAtHeight(100), + }, + Period: types.BlockDuration(10), + PeriodReset: types.ExpiresAtHeight(70), + PeriodSpendLimit: atom, + }, + valid: true, + fee: oneAtom, + blockHeight: 75, + accept: true, + remove: false, + remainsPeriod: smallAtom.Sub(oneAtom), + remains: smallAtom.Sub(oneAtom), + periodReset: types.ExpiresAtHeight(80), // one step from last reset, not now + }, + "expired": { + allow: types.PeriodicFeeAllowance{ + Basic: types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + Period: types.BlockDuration(10), + PeriodSpendLimit: smallAtom, + }, + valid: true, + fee: smallAtom, + blockHeight: 101, + accept: false, + remove: true, + }, + "over period limit": { + allow: types.PeriodicFeeAllowance{ + Basic: types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + Period: types.BlockDuration(10), + PeriodReset: types.ExpiresAtHeight(80), + PeriodSpendLimit: leftAtom, + PeriodCanSpend: smallAtom, + }, + valid: true, + fee: leftAtom, + blockHeight: 70, + accept: false, + remove: true, + }, + } + + for name, stc := range cases { + tc := stc // to make scopelint happy + t.Run(name, func(t *testing.T) { + err := tc.allow.ValidateBasic() + if !tc.valid { + require.Error(t, err) + return + } + require.NoError(t, err) + + // now try to deduct + remove, err := tc.allow.Accept(tc.fee, tc.blockTime, tc.blockHeight) + if !tc.accept { + require.Error(t, err) + return + } + require.NoError(t, err) + + require.Equal(t, tc.remove, remove) + if !remove { + assert.Equal(t, tc.remains, tc.allow.Basic.SpendLimit) + assert.Equal(t, tc.remainsPeriod, tc.allow.PeriodCanSpend) + assert.Equal(t, tc.periodReset, tc.allow.PeriodReset) + } + }) + } +} diff --git a/x/feegrant/types/query.pb.go b/x/feegrant/types/query.pb.go new file mode 100644 index 000000000000..e2597c3bc833 --- /dev/null +++ b/x/feegrant/types/query.pb.go @@ -0,0 +1,1172 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/feegrant/v1beta1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + query "github.com/cosmos/cosmos-sdk/types/query" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// QueryFeeAllowanceRequest is the request type for the Query/FeeAllowance RPC method. +type QueryFeeAllowanceRequest struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` +} + +func (m *QueryFeeAllowanceRequest) Reset() { *m = QueryFeeAllowanceRequest{} } +func (m *QueryFeeAllowanceRequest) String() string { return proto.CompactTextString(m) } +func (*QueryFeeAllowanceRequest) ProtoMessage() {} +func (*QueryFeeAllowanceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_59efc303945de53f, []int{0} +} +func (m *QueryFeeAllowanceRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryFeeAllowanceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryFeeAllowanceRequest.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 *QueryFeeAllowanceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryFeeAllowanceRequest.Merge(m, src) +} +func (m *QueryFeeAllowanceRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryFeeAllowanceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryFeeAllowanceRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryFeeAllowanceRequest proto.InternalMessageInfo + +func (m *QueryFeeAllowanceRequest) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *QueryFeeAllowanceRequest) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +// QueryFeeAllowanceResponse is the response type for the Query/FeeAllowance RPC method. +type QueryFeeAllowanceResponse struct { + // fee_allowance is a fee_allowance granted for grantee by granter. + FeeAllowance *FeeAllowanceGrant `protobuf:"bytes,1,opt,name=fee_allowance,json=feeAllowance,proto3" json:"fee_allowance,omitempty"` +} + +func (m *QueryFeeAllowanceResponse) Reset() { *m = QueryFeeAllowanceResponse{} } +func (m *QueryFeeAllowanceResponse) String() string { return proto.CompactTextString(m) } +func (*QueryFeeAllowanceResponse) ProtoMessage() {} +func (*QueryFeeAllowanceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_59efc303945de53f, []int{1} +} +func (m *QueryFeeAllowanceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryFeeAllowanceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryFeeAllowanceResponse.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 *QueryFeeAllowanceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryFeeAllowanceResponse.Merge(m, src) +} +func (m *QueryFeeAllowanceResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryFeeAllowanceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryFeeAllowanceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryFeeAllowanceResponse proto.InternalMessageInfo + +func (m *QueryFeeAllowanceResponse) GetFeeAllowance() *FeeAllowanceGrant { + if m != nil { + return m.FeeAllowance + } + return nil +} + +// QueryFeeAllowancesRequest is the request type for the Query/FeeAllowances RPC method. +type QueryFeeAllowancesRequest struct { + Grantee string `protobuf:"bytes,1,opt,name=grantee,proto3" json:"grantee,omitempty"` + // pagination defines an pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryFeeAllowancesRequest) Reset() { *m = QueryFeeAllowancesRequest{} } +func (m *QueryFeeAllowancesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryFeeAllowancesRequest) ProtoMessage() {} +func (*QueryFeeAllowancesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_59efc303945de53f, []int{2} +} +func (m *QueryFeeAllowancesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryFeeAllowancesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryFeeAllowancesRequest.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 *QueryFeeAllowancesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryFeeAllowancesRequest.Merge(m, src) +} +func (m *QueryFeeAllowancesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryFeeAllowancesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryFeeAllowancesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryFeeAllowancesRequest proto.InternalMessageInfo + +func (m *QueryFeeAllowancesRequest) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *QueryFeeAllowancesRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryFeeAllowancesResponse is the response type for the Query/FeeAllowances RPC method. +type QueryFeeAllowancesResponse struct { + // fee_allowances are fee_allowance's granted for grantee by granter. + FeeAllowances []*FeeAllowanceGrant `protobuf:"bytes,1,rep,name=fee_allowances,json=feeAllowances,proto3" json:"fee_allowances,omitempty"` + // pagination defines an pagination for the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryFeeAllowancesResponse) Reset() { *m = QueryFeeAllowancesResponse{} } +func (m *QueryFeeAllowancesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryFeeAllowancesResponse) ProtoMessage() {} +func (*QueryFeeAllowancesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_59efc303945de53f, []int{3} +} +func (m *QueryFeeAllowancesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryFeeAllowancesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryFeeAllowancesResponse.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 *QueryFeeAllowancesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryFeeAllowancesResponse.Merge(m, src) +} +func (m *QueryFeeAllowancesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryFeeAllowancesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryFeeAllowancesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryFeeAllowancesResponse proto.InternalMessageInfo + +func (m *QueryFeeAllowancesResponse) GetFeeAllowances() []*FeeAllowanceGrant { + if m != nil { + return m.FeeAllowances + } + return nil +} + +func (m *QueryFeeAllowancesResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +func init() { + proto.RegisterType((*QueryFeeAllowanceRequest)(nil), "cosmos.feegrant.v1beta1.QueryFeeAllowanceRequest") + proto.RegisterType((*QueryFeeAllowanceResponse)(nil), "cosmos.feegrant.v1beta1.QueryFeeAllowanceResponse") + proto.RegisterType((*QueryFeeAllowancesRequest)(nil), "cosmos.feegrant.v1beta1.QueryFeeAllowancesRequest") + proto.RegisterType((*QueryFeeAllowancesResponse)(nil), "cosmos.feegrant.v1beta1.QueryFeeAllowancesResponse") +} + +func init() { + proto.RegisterFile("cosmos/feegrant/v1beta1/query.proto", fileDescriptor_59efc303945de53f) +} + +var fileDescriptor_59efc303945de53f = []byte{ + // 455 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0x31, 0x8f, 0xd3, 0x30, + 0x14, 0xc7, 0xeb, 0x22, 0x40, 0xf8, 0xae, 0x0c, 0x16, 0x12, 0x21, 0x42, 0xd1, 0x29, 0x48, 0x07, + 0x3a, 0xe9, 0x62, 0x35, 0x9d, 0x40, 0x2c, 0xdc, 0x70, 0xdd, 0x80, 0xcb, 0xc8, 0x82, 0x9c, 0xf2, + 0x6a, 0x22, 0x72, 0x71, 0x2e, 0x76, 0x81, 0x13, 0xea, 0xc2, 0x27, 0x40, 0xe2, 0xa3, 0xb0, 0xc0, + 0x37, 0x60, 0x3c, 0x89, 0x85, 0x11, 0xb5, 0x7c, 0x09, 0x36, 0x14, 0x3b, 0x6e, 0x52, 0x91, 0x00, + 0x99, 0xe2, 0xe4, 0xfd, 0xdf, 0x7b, 0xbf, 0xf7, 0xcf, 0x33, 0xbe, 0x33, 0x13, 0xf2, 0x54, 0x48, + 0x3a, 0x07, 0xe0, 0x05, 0xcb, 0x14, 0x7d, 0x3d, 0x8e, 0x41, 0xb1, 0x31, 0x3d, 0x5b, 0x40, 0x71, + 0x1e, 0xe4, 0x85, 0x50, 0x82, 0xdc, 0x34, 0xa2, 0xc0, 0x8a, 0x82, 0x4a, 0xe4, 0xde, 0xe0, 0x82, + 0x0b, 0xad, 0xa1, 0xe5, 0xc9, 0xc8, 0xdd, 0xfd, 0xae, 0x9a, 0x9b, 0x7c, 0xa3, 0x3b, 0xa8, 0x74, + 0x31, 0x93, 0x60, 0xfa, 0x6d, 0x94, 0x39, 0xe3, 0x49, 0xc6, 0x54, 0x22, 0xb2, 0x4a, 0x7b, 0x9b, + 0x0b, 0xc1, 0x53, 0xa0, 0x2c, 0x4f, 0x28, 0xcb, 0x32, 0xa1, 0x74, 0x50, 0x9a, 0xa8, 0xff, 0x18, + 0x3b, 0x27, 0x65, 0xfe, 0x31, 0xc0, 0xa3, 0x34, 0x15, 0x6f, 0x58, 0x36, 0x83, 0x08, 0xce, 0x16, + 0x20, 0x15, 0x71, 0xf0, 0x55, 0xdd, 0x14, 0x0a, 0x07, 0xed, 0xa1, 0x7b, 0xd7, 0x22, 0xfb, 0x5a, + 0x47, 0xc0, 0x19, 0x36, 0x23, 0xe0, 0xa7, 0xf8, 0x56, 0x4b, 0x3d, 0x99, 0x8b, 0x4c, 0x02, 0x79, + 0x82, 0x47, 0x73, 0x80, 0xe7, 0xcc, 0x06, 0x74, 0xd9, 0x9d, 0xf0, 0x20, 0xe8, 0x70, 0x29, 0x68, + 0x56, 0x99, 0x96, 0x91, 0x68, 0x77, 0xde, 0xf8, 0xe4, 0x2f, 0x5b, 0xba, 0xc9, 0x3f, 0xf0, 0x61, + 0x1b, 0x1f, 0xc8, 0x31, 0xc6, 0xb5, 0x4d, 0x7a, 0x82, 0x9d, 0x70, 0xdf, 0x42, 0x94, 0x9e, 0x06, + 0xe6, 0x1f, 0x5a, 0x8c, 0xa7, 0x8c, 0x5b, 0x53, 0xa2, 0x46, 0xa6, 0xff, 0x19, 0x61, 0xb7, 0xad, + 0x7f, 0x35, 0xee, 0x09, 0xbe, 0xbe, 0x35, 0xae, 0x74, 0xd0, 0xde, 0xa5, 0x9e, 0xf3, 0x8e, 0x9a, + 0xf3, 0x4a, 0x32, 0x6d, 0x21, 0xbf, 0xfb, 0x4f, 0x72, 0xc3, 0xd3, 0x44, 0x0f, 0x7f, 0x0d, 0xf1, + 0x65, 0x8d, 0x4e, 0xbe, 0x20, 0xbc, 0xdb, 0xec, 0x4b, 0xc6, 0x9d, 0x78, 0x5d, 0x9b, 0xe2, 0x86, + 0x7d, 0x52, 0x0c, 0x8d, 0x7f, 0xf4, 0xfe, 0xdb, 0xcf, 0x8f, 0xc3, 0x87, 0xe4, 0x01, 0xfd, 0xcb, + 0xd2, 0xd7, 0xe6, 0xd1, 0x77, 0xd5, 0xf2, 0x2d, 0xed, 0x09, 0x96, 0xe4, 0x13, 0xc2, 0xa3, 0x2d, + 0xef, 0x49, 0x0f, 0x12, 0xbb, 0x28, 0xee, 0xa4, 0x57, 0x4e, 0x85, 0x7f, 0x5f, 0xe3, 0x4f, 0xc8, + 0xf8, 0xff, 0xf0, 0x65, 0x4d, 0x7d, 0x34, 0xfd, 0xba, 0xf2, 0xd0, 0xc5, 0xca, 0x43, 0x3f, 0x56, + 0x1e, 0xfa, 0xb0, 0xf6, 0x06, 0x17, 0x6b, 0x6f, 0xf0, 0x7d, 0xed, 0x0d, 0x9e, 0x1d, 0xf2, 0x44, + 0xbd, 0x5c, 0xc4, 0xc1, 0x4c, 0x9c, 0xda, 0xb2, 0xe6, 0x71, 0x28, 0x5f, 0xbc, 0xa2, 0x6f, 0xeb, + 0x1e, 0xea, 0x3c, 0x07, 0x19, 0x5f, 0xd1, 0x77, 0x78, 0xf2, 0x3b, 0x00, 0x00, 0xff, 0xff, 0xb8, + 0x46, 0x4c, 0xba, 0x8b, 0x04, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // FeeAllowance returns fee granted to the grantee by the granter. + FeeAllowance(ctx context.Context, in *QueryFeeAllowanceRequest, opts ...grpc.CallOption) (*QueryFeeAllowanceResponse, error) + // FeeAllowances returns all the grants for address. + FeeAllowances(ctx context.Context, in *QueryFeeAllowancesRequest, opts ...grpc.CallOption) (*QueryFeeAllowancesResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) FeeAllowance(ctx context.Context, in *QueryFeeAllowanceRequest, opts ...grpc.CallOption) (*QueryFeeAllowanceResponse, error) { + out := new(QueryFeeAllowanceResponse) + err := c.cc.Invoke(ctx, "/cosmos.feegrant.v1beta1.Query/FeeAllowance", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) FeeAllowances(ctx context.Context, in *QueryFeeAllowancesRequest, opts ...grpc.CallOption) (*QueryFeeAllowancesResponse, error) { + out := new(QueryFeeAllowancesResponse) + err := c.cc.Invoke(ctx, "/cosmos.feegrant.v1beta1.Query/FeeAllowances", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // FeeAllowance returns fee granted to the grantee by the granter. + FeeAllowance(context.Context, *QueryFeeAllowanceRequest) (*QueryFeeAllowanceResponse, error) + // FeeAllowances returns all the grants for address. + FeeAllowances(context.Context, *QueryFeeAllowancesRequest) (*QueryFeeAllowancesResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) FeeAllowance(ctx context.Context, req *QueryFeeAllowanceRequest) (*QueryFeeAllowanceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FeeAllowance not implemented") +} +func (*UnimplementedQueryServer) FeeAllowances(ctx context.Context, req *QueryFeeAllowancesRequest) (*QueryFeeAllowancesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FeeAllowances not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_FeeAllowance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryFeeAllowanceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).FeeAllowance(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.feegrant.v1beta1.Query/FeeAllowance", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).FeeAllowance(ctx, req.(*QueryFeeAllowanceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_FeeAllowances_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryFeeAllowancesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).FeeAllowances(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.feegrant.v1beta1.Query/FeeAllowances", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).FeeAllowances(ctx, req.(*QueryFeeAllowancesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cosmos.feegrant.v1beta1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "FeeAllowance", + Handler: _Query_FeeAllowance_Handler, + }, + { + MethodName: "FeeAllowances", + Handler: _Query_FeeAllowances_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cosmos/feegrant/v1beta1/query.proto", +} + +func (m *QueryFeeAllowanceRequest) 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 *QueryFeeAllowanceRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryFeeAllowanceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Granter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryFeeAllowanceResponse) 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 *QueryFeeAllowanceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryFeeAllowanceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.FeeAllowance != nil { + { + size, err := m.FeeAllowance.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 *QueryFeeAllowancesRequest) 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 *QueryFeeAllowancesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryFeeAllowancesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryFeeAllowancesResponse) 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 *QueryFeeAllowancesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryFeeAllowancesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.FeeAllowances) > 0 { + for iNdEx := len(m.FeeAllowances) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.FeeAllowances[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 encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryFeeAllowanceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryFeeAllowanceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.FeeAllowance != nil { + l = m.FeeAllowance.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryFeeAllowancesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryFeeAllowancesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.FeeAllowances) > 0 { + for _, e := range m.FeeAllowances { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryFeeAllowanceRequest) 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: QueryFeeAllowanceRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryFeeAllowanceRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryFeeAllowanceResponse) 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: QueryFeeAllowanceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryFeeAllowanceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FeeAllowance", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.FeeAllowance == nil { + m.FeeAllowance = &FeeAllowanceGrant{} + } + if err := m.FeeAllowance.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryFeeAllowancesRequest) 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: QueryFeeAllowancesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryFeeAllowancesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryFeeAllowancesResponse) 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: QueryFeeAllowancesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryFeeAllowancesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FeeAllowances", 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.FeeAllowances = append(m.FeeAllowances, &FeeAllowanceGrant{}) + if err := m.FeeAllowances[len(m.FeeAllowances)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/feegrant/types/query.pb.gw.go b/x/feegrant/types/query.pb.gw.go new file mode 100644 index 000000000000..499e4a441d18 --- /dev/null +++ b/x/feegrant/types/query.pb.gw.go @@ -0,0 +1,322 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: cosmos/feegrant/v1beta1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage + +func request_Query_FeeAllowance_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryFeeAllowanceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["granter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "granter") + } + + protoReq.Granter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "granter", err) + } + + val, ok = pathParams["grantee"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "grantee") + } + + protoReq.Grantee, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "grantee", err) + } + + msg, err := client.FeeAllowance(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_FeeAllowance_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryFeeAllowanceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["granter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "granter") + } + + protoReq.Granter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "granter", err) + } + + val, ok = pathParams["grantee"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "grantee") + } + + protoReq.Grantee, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "grantee", err) + } + + msg, err := server.FeeAllowance(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_FeeAllowances_0 = &utilities.DoubleArray{Encoding: map[string]int{"grantee": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_FeeAllowances_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryFeeAllowancesRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["grantee"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "grantee") + } + + protoReq.Grantee, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "grantee", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_FeeAllowances_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.FeeAllowances(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_FeeAllowances_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryFeeAllowancesRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["grantee"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "grantee") + } + + protoReq.Grantee, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "grantee", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_FeeAllowances_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.FeeAllowances(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_FeeAllowance_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_FeeAllowance_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_FeeAllowance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_FeeAllowances_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_FeeAllowances_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_FeeAllowances_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_FeeAllowance_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_FeeAllowance_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_FeeAllowance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_FeeAllowances_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_FeeAllowances_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_FeeAllowances_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_FeeAllowance_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"cosmos", "feegrant", "v1beta1", "fee_allowance", "granter", "grantee"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_FeeAllowances_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "feegrant", "v1beta1", "fee_allowances", "grantee"}, "", runtime.AssumeColonVerbOpt(true))) +) + +var ( + forward_Query_FeeAllowance_0 = runtime.ForwardResponseMessage + + forward_Query_FeeAllowances_0 = runtime.ForwardResponseMessage +) diff --git a/x/feegrant/types/tx.pb.go b/x/feegrant/types/tx.pb.go new file mode 100644 index 000000000000..d3080f10e3df --- /dev/null +++ b/x/feegrant/types/tx.pb.go @@ -0,0 +1,1033 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/feegrant/v1beta1/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + types "github.com/cosmos/cosmos-sdk/codec/types" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + _ "github.com/regen-network/cosmos-proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MsgGrantFeeAllowance adds permission for Grantee to spend up to Allowance +// of fees from the account of Granter. +type MsgGrantFeeAllowance struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` + Allowance *types.Any `protobuf:"bytes,3,opt,name=allowance,proto3" json:"allowance,omitempty"` +} + +func (m *MsgGrantFeeAllowance) Reset() { *m = MsgGrantFeeAllowance{} } +func (m *MsgGrantFeeAllowance) String() string { return proto.CompactTextString(m) } +func (*MsgGrantFeeAllowance) ProtoMessage() {} +func (*MsgGrantFeeAllowance) Descriptor() ([]byte, []int) { + return fileDescriptor_dd44ad7946dad783, []int{0} +} +func (m *MsgGrantFeeAllowance) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgGrantFeeAllowance) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgGrantFeeAllowance.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 *MsgGrantFeeAllowance) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgGrantFeeAllowance.Merge(m, src) +} +func (m *MsgGrantFeeAllowance) XXX_Size() int { + return m.Size() +} +func (m *MsgGrantFeeAllowance) XXX_DiscardUnknown() { + xxx_messageInfo_MsgGrantFeeAllowance.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgGrantFeeAllowance proto.InternalMessageInfo + +func (m *MsgGrantFeeAllowance) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *MsgGrantFeeAllowance) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *MsgGrantFeeAllowance) GetAllowance() *types.Any { + if m != nil { + return m.Allowance + } + return nil +} + +// MsgGrantFeeAllowanceResponse defines the Msg/GrantFeeAllowanceResponse response type. +type MsgGrantFeeAllowanceResponse struct { +} + +func (m *MsgGrantFeeAllowanceResponse) Reset() { *m = MsgGrantFeeAllowanceResponse{} } +func (m *MsgGrantFeeAllowanceResponse) String() string { return proto.CompactTextString(m) } +func (*MsgGrantFeeAllowanceResponse) ProtoMessage() {} +func (*MsgGrantFeeAllowanceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_dd44ad7946dad783, []int{1} +} +func (m *MsgGrantFeeAllowanceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgGrantFeeAllowanceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgGrantFeeAllowanceResponse.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 *MsgGrantFeeAllowanceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgGrantFeeAllowanceResponse.Merge(m, src) +} +func (m *MsgGrantFeeAllowanceResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgGrantFeeAllowanceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgGrantFeeAllowanceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgGrantFeeAllowanceResponse proto.InternalMessageInfo + +// MsgRevokeFeeAllowance removes any existing FeeAllowance from Granter to Grantee. +type MsgRevokeFeeAllowance struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` +} + +func (m *MsgRevokeFeeAllowance) Reset() { *m = MsgRevokeFeeAllowance{} } +func (m *MsgRevokeFeeAllowance) String() string { return proto.CompactTextString(m) } +func (*MsgRevokeFeeAllowance) ProtoMessage() {} +func (*MsgRevokeFeeAllowance) Descriptor() ([]byte, []int) { + return fileDescriptor_dd44ad7946dad783, []int{2} +} +func (m *MsgRevokeFeeAllowance) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRevokeFeeAllowance) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRevokeFeeAllowance.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 *MsgRevokeFeeAllowance) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRevokeFeeAllowance.Merge(m, src) +} +func (m *MsgRevokeFeeAllowance) XXX_Size() int { + return m.Size() +} +func (m *MsgRevokeFeeAllowance) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRevokeFeeAllowance.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRevokeFeeAllowance proto.InternalMessageInfo + +func (m *MsgRevokeFeeAllowance) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *MsgRevokeFeeAllowance) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +// MsgRevokeFeeAllowanceResponse defines the Msg/RevokeFeeAllowanceResponse response type. +type MsgRevokeFeeAllowanceResponse struct { +} + +func (m *MsgRevokeFeeAllowanceResponse) Reset() { *m = MsgRevokeFeeAllowanceResponse{} } +func (m *MsgRevokeFeeAllowanceResponse) String() string { return proto.CompactTextString(m) } +func (*MsgRevokeFeeAllowanceResponse) ProtoMessage() {} +func (*MsgRevokeFeeAllowanceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_dd44ad7946dad783, []int{3} +} +func (m *MsgRevokeFeeAllowanceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRevokeFeeAllowanceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRevokeFeeAllowanceResponse.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 *MsgRevokeFeeAllowanceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRevokeFeeAllowanceResponse.Merge(m, src) +} +func (m *MsgRevokeFeeAllowanceResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgRevokeFeeAllowanceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRevokeFeeAllowanceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRevokeFeeAllowanceResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgGrantFeeAllowance)(nil), "cosmos.feegrant.v1beta1.MsgGrantFeeAllowance") + proto.RegisterType((*MsgGrantFeeAllowanceResponse)(nil), "cosmos.feegrant.v1beta1.MsgGrantFeeAllowanceResponse") + proto.RegisterType((*MsgRevokeFeeAllowance)(nil), "cosmos.feegrant.v1beta1.MsgRevokeFeeAllowance") + proto.RegisterType((*MsgRevokeFeeAllowanceResponse)(nil), "cosmos.feegrant.v1beta1.MsgRevokeFeeAllowanceResponse") +} + +func init() { proto.RegisterFile("cosmos/feegrant/v1beta1/tx.proto", fileDescriptor_dd44ad7946dad783) } + +var fileDescriptor_dd44ad7946dad783 = []byte{ + // 345 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x48, 0xce, 0x2f, 0xce, + 0xcd, 0x2f, 0xd6, 0x4f, 0x4b, 0x4d, 0x4d, 0x2f, 0x4a, 0xcc, 0x2b, 0xd1, 0x2f, 0x33, 0x4c, 0x4a, + 0x2d, 0x49, 0x34, 0xd4, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x87, 0xa8, + 0xd0, 0x83, 0xa9, 0xd0, 0x83, 0xaa, 0x90, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0xab, 0xd1, 0x07, + 0xb1, 0x20, 0xca, 0xa5, 0x24, 0xd3, 0xf3, 0xf3, 0xd3, 0x73, 0x52, 0xf5, 0xc1, 0xbc, 0xa4, 0xd2, + 0x34, 0xfd, 0xc4, 0xbc, 0x4a, 0x98, 0x14, 0xc4, 0xa4, 0x78, 0x88, 0x1e, 0xa8, 0xb1, 0x60, 0x8e, + 0xd2, 0x44, 0x46, 0x2e, 0x11, 0xdf, 0xe2, 0x74, 0x77, 0x90, 0x05, 0x6e, 0xa9, 0xa9, 0x8e, 0x39, + 0x39, 0xf9, 0xe5, 0x89, 0x79, 0xc9, 0xa9, 0x42, 0x12, 0x5c, 0xec, 0x60, 0x5b, 0x53, 0x8b, 0x24, + 0x18, 0x15, 0x18, 0x35, 0x38, 0x83, 0x60, 0x5c, 0x84, 0x4c, 0xaa, 0x04, 0x13, 0xb2, 0x4c, 0xaa, + 0x90, 0x2b, 0x17, 0x67, 0x22, 0xcc, 0x00, 0x09, 0x66, 0x05, 0x46, 0x0d, 0x6e, 0x23, 0x11, 0x3d, + 0x88, 0xb3, 0xf4, 0x60, 0xce, 0xd2, 0x73, 0xcc, 0xab, 0x74, 0x12, 0x3c, 0xb5, 0x45, 0x97, 0x17, + 0xd9, 0x3a, 0xcf, 0x20, 0x84, 0x4e, 0x25, 0x39, 0x2e, 0x19, 0x6c, 0x4e, 0x0a, 0x4a, 0x2d, 0x2e, + 0xc8, 0xcf, 0x2b, 0x4e, 0x55, 0xf2, 0xe6, 0x12, 0xf5, 0x2d, 0x4e, 0x0f, 0x4a, 0x2d, 0xcb, 0xcf, + 0x4e, 0xa5, 0xd4, 0xcd, 0x4a, 0xf2, 0x5c, 0xb2, 0x58, 0x0d, 0x83, 0xd9, 0x66, 0xf4, 0x8f, 0x91, + 0x8b, 0xd9, 0xb7, 0x38, 0x5d, 0xa8, 0x92, 0x4b, 0x10, 0x33, 0x94, 0x74, 0xf5, 0x70, 0x44, 0x92, + 0x1e, 0x36, 0x1f, 0x48, 0x99, 0x92, 0xa4, 0x1c, 0xe6, 0x04, 0xa1, 0x1a, 0x2e, 0x21, 0x2c, 0xbe, + 0xd5, 0xc3, 0x67, 0x18, 0xa6, 0x7a, 0x29, 0x33, 0xd2, 0xd4, 0xc3, 0x6c, 0x77, 0x72, 0x3f, 0xf1, + 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, + 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0xdd, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, + 0xbd, 0xe4, 0xfc, 0x5c, 0x68, 0xaa, 0x82, 0x52, 0xba, 0xc5, 0x29, 0xd9, 0xfa, 0x15, 0x88, 0xb4, + 0x5d, 0x52, 0x59, 0x90, 0x5a, 0x9c, 0xc4, 0x06, 0x4e, 0x03, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x7b, 0xbe, 0x24, 0x15, 0xfb, 0x02, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // GrantFeeAllowance grants fee allowance to the grantee on the granter's + // account with the provided expiration time. + GrantFeeAllowance(ctx context.Context, in *MsgGrantFeeAllowance, opts ...grpc.CallOption) (*MsgGrantFeeAllowanceResponse, error) + // RevokeFeeAllowance revokes any fee allowance of granter's account that + // has been granted to the grantee. + RevokeFeeAllowance(ctx context.Context, in *MsgRevokeFeeAllowance, opts ...grpc.CallOption) (*MsgRevokeFeeAllowanceResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) GrantFeeAllowance(ctx context.Context, in *MsgGrantFeeAllowance, opts ...grpc.CallOption) (*MsgGrantFeeAllowanceResponse, error) { + out := new(MsgGrantFeeAllowanceResponse) + err := c.cc.Invoke(ctx, "/cosmos.feegrant.v1beta1.Msg/GrantFeeAllowance", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) RevokeFeeAllowance(ctx context.Context, in *MsgRevokeFeeAllowance, opts ...grpc.CallOption) (*MsgRevokeFeeAllowanceResponse, error) { + out := new(MsgRevokeFeeAllowanceResponse) + err := c.cc.Invoke(ctx, "/cosmos.feegrant.v1beta1.Msg/RevokeFeeAllowance", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // GrantFeeAllowance grants fee allowance to the grantee on the granter's + // account with the provided expiration time. + GrantFeeAllowance(context.Context, *MsgGrantFeeAllowance) (*MsgGrantFeeAllowanceResponse, error) + // RevokeFeeAllowance revokes any fee allowance of granter's account that + // has been granted to the grantee. + RevokeFeeAllowance(context.Context, *MsgRevokeFeeAllowance) (*MsgRevokeFeeAllowanceResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) GrantFeeAllowance(ctx context.Context, req *MsgGrantFeeAllowance) (*MsgGrantFeeAllowanceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GrantFeeAllowance not implemented") +} +func (*UnimplementedMsgServer) RevokeFeeAllowance(ctx context.Context, req *MsgRevokeFeeAllowance) (*MsgRevokeFeeAllowanceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RevokeFeeAllowance not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_GrantFeeAllowance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgGrantFeeAllowance) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).GrantFeeAllowance(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.feegrant.v1beta1.Msg/GrantFeeAllowance", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).GrantFeeAllowance(ctx, req.(*MsgGrantFeeAllowance)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_RevokeFeeAllowance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgRevokeFeeAllowance) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).RevokeFeeAllowance(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.feegrant.v1beta1.Msg/RevokeFeeAllowance", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).RevokeFeeAllowance(ctx, req.(*MsgRevokeFeeAllowance)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cosmos.feegrant.v1beta1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GrantFeeAllowance", + Handler: _Msg_GrantFeeAllowance_Handler, + }, + { + MethodName: "RevokeFeeAllowance", + Handler: _Msg_RevokeFeeAllowance_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cosmos/feegrant/v1beta1/tx.proto", +} + +func (m *MsgGrantFeeAllowance) 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 *MsgGrantFeeAllowance) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgGrantFeeAllowance) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Allowance != nil { + { + size, err := m.Allowance.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintTx(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintTx(dAtA, i, uint64(len(m.Granter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgGrantFeeAllowanceResponse) 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 *MsgGrantFeeAllowanceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgGrantFeeAllowanceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgRevokeFeeAllowance) 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 *MsgRevokeFeeAllowance) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRevokeFeeAllowance) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintTx(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintTx(dAtA, i, uint64(len(m.Granter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgRevokeFeeAllowanceResponse) 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 *MsgRevokeFeeAllowanceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRevokeFeeAllowanceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgGrantFeeAllowance) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Allowance != nil { + l = m.Allowance.Size() + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgGrantFeeAllowanceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgRevokeFeeAllowance) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgRevokeFeeAllowanceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgGrantFeeAllowance) 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 ErrIntOverflowTx + } + 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: MsgGrantFeeAllowance: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgGrantFeeAllowance: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Allowance", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Allowance == nil { + m.Allowance = &types.Any{} + } + if err := m.Allowance.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgGrantFeeAllowanceResponse) 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 ErrIntOverflowTx + } + 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: MsgGrantFeeAllowanceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgGrantFeeAllowanceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRevokeFeeAllowance) 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 ErrIntOverflowTx + } + 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: MsgRevokeFeeAllowance: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRevokeFeeAllowance: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRevokeFeeAllowanceResponse) 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 ErrIntOverflowTx + } + 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: MsgRevokeFeeAllowanceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRevokeFeeAllowanceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/mint/simulation/decoder.go b/x/mint/simulation/decoder.go index 37d9930f7da5..f0a89be43965 100644 --- a/x/mint/simulation/decoder.go +++ b/x/mint/simulation/decoder.go @@ -9,7 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/mint/types" ) -// NewDecodeStore returns a decoder function closure that umarshals the KVPair's +// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's // Value to the corresponding mint type. func NewDecodeStore(cdc codec.Marshaler) func(kvA, kvB kv.Pair) string { return func(kvA, kvB kv.Pair) string { From d6e4a2e9bcd9eff87d6f4b43ae13378e2ba6ac63 Mon Sep 17 00:00:00 2001 From: yihuang Date: Sat, 30 Jan 2021 04:05:24 +0800 Subject: [PATCH 088/152] fix bech32 prefix in evidence (#8461) Co-authored-by: Tomas Tauber <2410580+tomtau@users.noreply.github.com> Co-authored-by: Tomas Tauber <2410580+tomtau@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- CHANGELOG.md | 1 + x/evidence/types/evidence.go | 3 ++- x/evidence/types/evidence_test.go | 20 ++++++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ea84cb3475f..6bfebd9d2b69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes +* (x/evidence) [#8461](https://github.com/cosmos/cosmos-sdk/pull/8461) Fix bech32 prefix in evidence validator address conversion * (x/slashing) [\#8427](https://github.com/cosmos/cosmos-sdk/pull/8427) Fix query signing infos command * (simapp) [\#8418](https://github.com/cosmos/cosmos-sdk/pull/8418) Add balance coin to supply when adding a new genesis account * (x/bank) [\#8417](https://github.com/cosmos/cosmos-sdk/pull/8417) Validate balances and coin denom metadata on genesis diff --git a/x/evidence/types/evidence.go b/x/evidence/types/evidence.go index 95705cc5b937..fca6126ec36f 100644 --- a/x/evidence/types/evidence.go +++ b/x/evidence/types/evidence.go @@ -88,7 +88,8 @@ func (e Equivocation) GetTotalPower() int64 { return 0 } // FromABCIEvidence converts a Tendermint concrete Evidence type to // SDK Evidence using Equivocation as the concrete type. func FromABCIEvidence(e abci.Evidence) exported.Evidence { - consAddr, err := sdk.Bech32ifyAddressBytes(sdk.Bech32PrefixConsAddr, e.Validator.Address) + bech32PrefixConsAddr := sdk.GetConfig().GetBech32ConsensusAddrPrefix() + consAddr, err := sdk.Bech32ifyAddressBytes(bech32PrefixConsAddr, e.Validator.Address) if err != nil { panic(err) } diff --git a/x/evidence/types/evidence_test.go b/x/evidence/types/evidence_test.go index 07b9352f574d..c78f0b059cc9 100644 --- a/x/evidence/types/evidence_test.go +++ b/x/evidence/types/evidence_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/evidence/types" @@ -57,3 +58,22 @@ func TestEquivocationValidateBasic(t *testing.T) { }) } } + +func TestEvidenceAddressConversion(t *testing.T) { + sdk.GetConfig().SetBech32PrefixForConsensusNode("testcnclcons", "testcnclconspub") + tmEvidence := abci.Evidence{ + Type: abci.EvidenceType_DUPLICATE_VOTE, + Validator: abci.Validator{ + Address: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + Power: 100, + }, + Height: 1, + Time: time.Now(), + TotalVotingPower: 100, + } + evidence := types.FromABCIEvidence(tmEvidence).(*types.Equivocation) + consAddr := evidence.GetConsensusAddress() + // Check the address is the same after conversion + require.Equal(t, tmEvidence.Validator.Address, consAddr.Bytes()) + sdk.GetConfig().SetBech32PrefixForConsensusNode(sdk.Bech32PrefixConsAddr, sdk.Bech32PrefixConsPub) +} From 1d75e0e984e7132efd54c3526e36b3585e2d91c0 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Fri, 29 Jan 2021 23:48:26 -0300 Subject: [PATCH 089/152] bank: additional client metadata validation (#8479) * bank: additional client metadata validation * changelog and comment * fix tab --- CHANGELOG.md | 1 + x/bank/types/metadata.go | 39 +++++++++++++++++++++++-- x/bank/types/metadata_test.go | 55 ++++++++++++++++++++++++++++++++++- 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bfebd9d2b69..5bcb99bd84c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (x/bank) [\#8479](https://github.com/cosmos/cosmos-sdk/pull/8479) Adittional client denom metadata validation for `base` and `display` denoms. * (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks. * [\#8396](https://github.com/cosmos/cosmos-sdk/pull/8396) Add support for ARM platform diff --git a/x/bank/types/metadata.go b/x/bank/types/metadata.go index 5106964e994e..ce7794053d93 100644 --- a/x/bank/types/metadata.go +++ b/x/bank/types/metadata.go @@ -1,13 +1,19 @@ package types import ( + "errors" "fmt" "strings" sdk "github.com/cosmos/cosmos-sdk/types" ) -// Validate performs a basic validation of the coin metadata fields +// Validate performs a basic validation of the coin metadata fields. It checks: +// - Base and Display denominations are valid coin denominations +// - Base and Display denominations are present in the DenomUnit slice +// - Base denomination has exponent 0 +// - Denomination units are sorted in ascending order +// - Denomination units not duplicated func (m Metadata) Validate() error { if err := sdk.ValidateDenom(m.Base); err != nil { return fmt.Errorf("invalid metadata base denom: %w", err) @@ -17,12 +23,37 @@ func (m Metadata) Validate() error { return fmt.Errorf("invalid metadata display denom: %w", err) } + var ( + hasDisplay bool + currentExponent uint32 // check that the exponents are increasing + ) + seenUnits := make(map[string]bool) - for _, denomUnit := range m.DenomUnits { + + for i, denomUnit := range m.DenomUnits { + // The first denomination unit MUST be the base + if i == 0 { + // validate denomination and exponent + if denomUnit.Denom != m.Base { + return fmt.Errorf("metadata's first denomination unit must be the one with base denom '%s'", m.Base) + } + if denomUnit.Exponent != 0 { + return fmt.Errorf("the exponent for base denomination unit %s must be 0", m.Base) + } + } else if currentExponent >= denomUnit.Exponent { + return errors.New("denom units should be sorted asc by exponent") + } + + currentExponent = denomUnit.Exponent + if seenUnits[denomUnit.Denom] { return fmt.Errorf("duplicate denomination unit %s", denomUnit.Denom) } + if denomUnit.Denom == m.Display { + hasDisplay = true + } + if err := denomUnit.Validate(); err != nil { return err } @@ -30,6 +61,10 @@ func (m Metadata) Validate() error { seenUnits[denomUnit.Denom] = true } + if !hasDisplay { + return fmt.Errorf("metadata must contain a denomination unit with display denom '%s'", m.Display) + } + return nil } diff --git a/x/bank/types/metadata_test.go b/x/bank/types/metadata_test.go index 29f4d220f95f..64241e6098e0 100644 --- a/x/bank/types/metadata_test.go +++ b/x/bank/types/metadata_test.go @@ -51,7 +51,7 @@ func TestMetadataValidate(t *testing.T) { Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ {"uatom", uint32(0), []string{"microatom"}}, - {"uatom", uint32(0), []string{"microatom"}}, + {"uatom", uint32(1), []string{"microatom"}}, }, Base: "uatom", Display: "atom", @@ -94,6 +94,59 @@ func TestMetadataValidate(t *testing.T) { }, true, }, + { + "no base denom unit", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"matom", uint32(3), []string{"milliatom"}}, + {"atom", uint32(6), nil}, + }, + Base: "uatom", + Display: "atom", + }, + true, + }, + { + "base denom exponent not zero", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"uatom", uint32(1), []string{"microatom"}}, + {"matom", uint32(3), []string{"milliatom"}}, + {"atom", uint32(6), nil}, + }, + Base: "uatom", + Display: "atom", + }, + true, + }, + { + "no display denom unit", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, + }, + Base: "uatom", + Display: "atom", + }, + true, + }, + { + "denom units not sorted", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, + {"atom", uint32(6), nil}, + {"matom", uint32(3), []string{"milliatom"}}, + }, + Base: "uatom", + Display: "atom", + }, + true, + }, } for _, tc := range testCases { From 812835795693bd6202a5c19d5f37724e69e204b2 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 1 Feb 2021 10:48:32 +0000 Subject: [PATCH 090/152] snapshots: fix flaky tests (#8475) The use testing.T.TempDir() seems to cause test failures in CI environvements in those cases where temporary directories' subdirs are created with permissions that are different from the defaults used by testing.T.TempDir(). The snapshots package's tests seem to be heavily affected, thus this replaces testing.T.TempDir() occurrences with ioutil.TempDir() calls. Related upstream issue: - https://github.com/golang/go/issues/40853 Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- snapshots/helpers_test.go | 6 +++++- snapshots/store_test.go | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/snapshots/helpers_test.go b/snapshots/helpers_test.go index 5dbdd317536a..751ac212d352 100644 --- a/snapshots/helpers_test.go +++ b/snapshots/helpers_test.go @@ -6,6 +6,7 @@ import ( "errors" "io" "io/ioutil" + "os" "testing" "time" @@ -100,7 +101,10 @@ func (m *mockSnapshotter) Snapshot(height uint64, format uint32) (<-chan io.Read // setupBusyManager creates a manager with an empty store that is busy creating a snapshot at height 1. // The snapshot will complete when the returned closer is called. func setupBusyManager(t *testing.T) *snapshots.Manager { - tempdir := t.TempDir() + tempdir, err := ioutil.TempDir("", "") + require.NoError(t, err) + t.Cleanup(func() { _ = os.RemoveAll(tempdir) }) + store, err := snapshots.NewStore(db.NewMemDB(), tempdir) require.NoError(t, err) hung := newHungSnapshotter() diff --git a/snapshots/store_test.go b/snapshots/store_test.go index 1a04a393c1ed..325fd3410bea 100644 --- a/snapshots/store_test.go +++ b/snapshots/store_test.go @@ -5,6 +5,7 @@ import ( "errors" "io" "io/ioutil" + "os" "path/filepath" "testing" "time" @@ -19,7 +20,10 @@ import ( ) func setupStore(t *testing.T) *snapshots.Store { - tempdir := t.TempDir() + tempdir, err := ioutil.TempDir("", "") + require.NoError(t, err) + t.Cleanup(func() { _ = os.RemoveAll(tempdir) }) + store, err := snapshots.NewStore(db.NewMemDB(), tempdir) require.NoError(t, err) From 896eee213ae39a327826000f5ef87f251789fbaf Mon Sep 17 00:00:00 2001 From: Amaury Date: Mon, 1 Feb 2021 13:35:18 +0100 Subject: [PATCH 091/152] docs: Update x/staking spec (#8395) * Finish updating state * Add messages * Update events * proto-gen * Update proto/cosmos/staking/v1beta1/staking.proto Co-authored-by: Anil Kumar Kammari * progo-gen * Update Msg with slash * Rerun proto docs Co-authored-by: Anil Kumar Kammari Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/core/proto-docs.md | 8220 ++++++++++---------- proto/cosmos/staking/v1beta1/staking.proto | 44 + x/staking/spec/01_state.md | 146 +- x/staking/spec/02_state_transitions.md | 25 +- x/staking/spec/03_messages.md | 101 +- x/staking/spec/07_events.md | 16 +- x/staking/spec/README.md | 18 +- x/staking/types/staking.pb.go | 120 +- 8 files changed, 4338 insertions(+), 4352 deletions(-) diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 6b5909a3dbc3..b06aaf246185 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -4,116 +4,70 @@ ## Table of Contents -- [cosmos/tx/v1beta1/tx.proto](#cosmos/tx/v1beta1/tx.proto) - - [AuthInfo](#cosmos.tx.v1beta1.AuthInfo) - - [Fee](#cosmos.tx.v1beta1.Fee) - - [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) - - [ModeInfo.Multi](#cosmos.tx.v1beta1.ModeInfo.Multi) - - [ModeInfo.Single](#cosmos.tx.v1beta1.ModeInfo.Single) - - [SignDoc](#cosmos.tx.v1beta1.SignDoc) - - [SignerInfo](#cosmos.tx.v1beta1.SignerInfo) - - [Tx](#cosmos.tx.v1beta1.Tx) - - [TxBody](#cosmos.tx.v1beta1.TxBody) - - [TxRaw](#cosmos.tx.v1beta1.TxRaw) - -- [cosmos/tx/v1beta1/service.proto](#cosmos/tx/v1beta1/service.proto) - - [BroadcastTxRequest](#cosmos.tx.v1beta1.BroadcastTxRequest) - - [BroadcastTxResponse](#cosmos.tx.v1beta1.BroadcastTxResponse) - - [GetTxRequest](#cosmos.tx.v1beta1.GetTxRequest) - - [GetTxResponse](#cosmos.tx.v1beta1.GetTxResponse) - - [GetTxsEventRequest](#cosmos.tx.v1beta1.GetTxsEventRequest) - - [GetTxsEventResponse](#cosmos.tx.v1beta1.GetTxsEventResponse) - - [SimulateRequest](#cosmos.tx.v1beta1.SimulateRequest) - - [SimulateResponse](#cosmos.tx.v1beta1.SimulateResponse) - - - [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) - - - [Service](#cosmos.tx.v1beta1.Service) - -- [cosmos/tx/signing/v1beta1/signing.proto](#cosmos/tx/signing/v1beta1/signing.proto) - - [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) - - [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) - - [SignatureDescriptor.Data.Multi](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Multi) - - [SignatureDescriptor.Data.Single](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Single) - - [SignatureDescriptors](#cosmos.tx.signing.v1beta1.SignatureDescriptors) - - - [SignMode](#cosmos.tx.signing.v1beta1.SignMode) - -- [cosmos/crisis/v1beta1/tx.proto](#cosmos/crisis/v1beta1/tx.proto) - - [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) - - [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) - - - [Msg](#cosmos.crisis.v1beta1.Msg) - -- [cosmos/crisis/v1beta1/genesis.proto](#cosmos/crisis/v1beta1/genesis.proto) - - [GenesisState](#cosmos.crisis.v1beta1.GenesisState) - -- [cosmos/crypto/multisig/keys.proto](#cosmos/crypto/multisig/keys.proto) - - [LegacyAminoPubKey](#cosmos.crypto.multisig.LegacyAminoPubKey) - -- [cosmos/crypto/multisig/v1beta1/multisig.proto](#cosmos/crypto/multisig/v1beta1/multisig.proto) - - [CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) - - [MultiSignature](#cosmos.crypto.multisig.v1beta1.MultiSignature) - -- [cosmos/crypto/secp256k1/keys.proto](#cosmos/crypto/secp256k1/keys.proto) - - [PrivKey](#cosmos.crypto.secp256k1.PrivKey) - - [PubKey](#cosmos.crypto.secp256k1.PubKey) - -- [cosmos/crypto/ed25519/keys.proto](#cosmos/crypto/ed25519/keys.proto) - - [PrivKey](#cosmos.crypto.ed25519.PrivKey) - - [PubKey](#cosmos.crypto.ed25519.PubKey) +- [cosmos/auth/v1beta1/auth.proto](#cosmos/auth/v1beta1/auth.proto) + - [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) + - [ModuleAccount](#cosmos.auth.v1beta1.ModuleAccount) + - [Params](#cosmos.auth.v1beta1.Params) -- [cosmos/mint/v1beta1/query.proto](#cosmos/mint/v1beta1/query.proto) - - [QueryAnnualProvisionsRequest](#cosmos.mint.v1beta1.QueryAnnualProvisionsRequest) - - [QueryAnnualProvisionsResponse](#cosmos.mint.v1beta1.QueryAnnualProvisionsResponse) - - [QueryInflationRequest](#cosmos.mint.v1beta1.QueryInflationRequest) - - [QueryInflationResponse](#cosmos.mint.v1beta1.QueryInflationResponse) - - [QueryParamsRequest](#cosmos.mint.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.mint.v1beta1.QueryParamsResponse) +- [cosmos/auth/v1beta1/genesis.proto](#cosmos/auth/v1beta1/genesis.proto) + - [GenesisState](#cosmos.auth.v1beta1.GenesisState) - - [Query](#cosmos.mint.v1beta1.Query) +- [cosmos/auth/v1beta1/query.proto](#cosmos/auth/v1beta1/query.proto) + - [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) + - [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) + - [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) -- [cosmos/mint/v1beta1/genesis.proto](#cosmos/mint/v1beta1/genesis.proto) - - [GenesisState](#cosmos.mint.v1beta1.GenesisState) + - [Query](#cosmos.auth.v1beta1.Query) -- [cosmos/mint/v1beta1/mint.proto](#cosmos/mint/v1beta1/mint.proto) - - [Minter](#cosmos.mint.v1beta1.Minter) - - [Params](#cosmos.mint.v1beta1.Params) +- [cosmos/base/v1beta1/coin.proto](#cosmos/base/v1beta1/coin.proto) + - [Coin](#cosmos.base.v1beta1.Coin) + - [DecCoin](#cosmos.base.v1beta1.DecCoin) + - [DecProto](#cosmos.base.v1beta1.DecProto) + - [IntProto](#cosmos.base.v1beta1.IntProto) -- [cosmos/feegrant/v1beta1/feegrant.proto](#cosmos/feegrant/v1beta1/feegrant.proto) - - [BasicFeeAllowance](#cosmos.feegrant.v1beta1.BasicFeeAllowance) - - [Duration](#cosmos.feegrant.v1beta1.Duration) - - [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) - - [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) - - [PeriodicFeeAllowance](#cosmos.feegrant.v1beta1.PeriodicFeeAllowance) +- [cosmos/authz/v1beta1/authz.proto](#cosmos/authz/v1beta1/authz.proto) + - [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) + - [GenericAuthorization](#cosmos.authz.v1beta1.GenericAuthorization) + - [SendAuthorization](#cosmos.authz.v1beta1.SendAuthorization) -- [cosmos/feegrant/v1beta1/query.proto](#cosmos/feegrant/v1beta1/query.proto) - - [QueryFeeAllowanceRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowanceRequest) - - [QueryFeeAllowanceResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowanceResponse) - - [QueryFeeAllowancesRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowancesRequest) - - [QueryFeeAllowancesResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowancesResponse) +- [cosmos/base/abci/v1beta1/abci.proto](#cosmos/base/abci/v1beta1/abci.proto) + - [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) + - [Attribute](#cosmos.base.abci.v1beta1.Attribute) + - [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) + - [MsgData](#cosmos.base.abci.v1beta1.MsgData) + - [Result](#cosmos.base.abci.v1beta1.Result) + - [SearchTxsResult](#cosmos.base.abci.v1beta1.SearchTxsResult) + - [SimulationResponse](#cosmos.base.abci.v1beta1.SimulationResponse) + - [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) + - [TxMsgData](#cosmos.base.abci.v1beta1.TxMsgData) + - [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) - - [Query](#cosmos.feegrant.v1beta1.Query) +- [cosmos/authz/v1beta1/tx.proto](#cosmos/authz/v1beta1/tx.proto) + - [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) + - [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) + - [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) + - [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) + - [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) + - [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) -- [cosmos/feegrant/v1beta1/tx.proto](#cosmos/feegrant/v1beta1/tx.proto) - - [MsgGrantFeeAllowance](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowance) - - [MsgGrantFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowanceResponse) - - [MsgRevokeFeeAllowance](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowance) - - [MsgRevokeFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowanceResponse) + - [Msg](#cosmos.authz.v1beta1.Msg) - - [Msg](#cosmos.feegrant.v1beta1.Msg) +- [cosmos/authz/v1beta1/genesis.proto](#cosmos/authz/v1beta1/genesis.proto) + - [GenesisState](#cosmos.authz.v1beta1.GenesisState) + - [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) -- [cosmos/feegrant/v1beta1/genesis.proto](#cosmos/feegrant/v1beta1/genesis.proto) - - [GenesisState](#cosmos.feegrant.v1beta1.GenesisState) +- [cosmos/base/query/v1beta1/pagination.proto](#cosmos/base/query/v1beta1/pagination.proto) + - [PageRequest](#cosmos.base.query.v1beta1.PageRequest) + - [PageResponse](#cosmos.base.query.v1beta1.PageResponse) -- [cosmos/capability/v1beta1/capability.proto](#cosmos/capability/v1beta1/capability.proto) - - [Capability](#cosmos.capability.v1beta1.Capability) - - [CapabilityOwners](#cosmos.capability.v1beta1.CapabilityOwners) - - [Owner](#cosmos.capability.v1beta1.Owner) +- [cosmos/authz/v1beta1/query.proto](#cosmos/authz/v1beta1/query.proto) + - [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) + - [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) + - [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) + - [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) -- [cosmos/capability/v1beta1/genesis.proto](#cosmos/capability/v1beta1/genesis.proto) - - [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) - - [GenesisState](#cosmos.capability.v1beta1.GenesisState) + - [Query](#cosmos.authz.v1beta1.Query) - [cosmos/bank/v1beta1/bank.proto](#cosmos/bank/v1beta1/bank.proto) - [DenomUnit](#cosmos.bank.v1beta1.DenomUnit) @@ -124,6 +78,10 @@ - [SendEnabled](#cosmos.bank.v1beta1.SendEnabled) - [Supply](#cosmos.bank.v1beta1.Supply) +- [cosmos/bank/v1beta1/genesis.proto](#cosmos/bank/v1beta1/genesis.proto) + - [Balance](#cosmos.bank.v1beta1.Balance) + - [GenesisState](#cosmos.bank.v1beta1.GenesisState) + - [cosmos/bank/v1beta1/query.proto](#cosmos/bank/v1beta1/query.proto) - [QueryAllBalancesRequest](#cosmos.bank.v1beta1.QueryAllBalancesRequest) - [QueryAllBalancesResponse](#cosmos.bank.v1beta1.QueryAllBalancesResponse) @@ -150,85 +108,107 @@ - [Msg](#cosmos.bank.v1beta1.Msg) -- [cosmos/bank/v1beta1/genesis.proto](#cosmos/bank/v1beta1/genesis.proto) - - [Balance](#cosmos.bank.v1beta1.Balance) - - [GenesisState](#cosmos.bank.v1beta1.GenesisState) +- [cosmos/base/kv/v1beta1/kv.proto](#cosmos/base/kv/v1beta1/kv.proto) + - [Pair](#cosmos.base.kv.v1beta1.Pair) + - [Pairs](#cosmos.base.kv.v1beta1.Pairs) -- [cosmos/authz/v1beta1/authz.proto](#cosmos/authz/v1beta1/authz.proto) - - [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) - - [GenericAuthorization](#cosmos.authz.v1beta1.GenericAuthorization) - - [SendAuthorization](#cosmos.authz.v1beta1.SendAuthorization) +- [cosmos/base/reflection/v1beta1/reflection.proto](#cosmos/base/reflection/v1beta1/reflection.proto) + - [ListAllInterfacesRequest](#cosmos.base.reflection.v1beta1.ListAllInterfacesRequest) + - [ListAllInterfacesResponse](#cosmos.base.reflection.v1beta1.ListAllInterfacesResponse) + - [ListImplementationsRequest](#cosmos.base.reflection.v1beta1.ListImplementationsRequest) + - [ListImplementationsResponse](#cosmos.base.reflection.v1beta1.ListImplementationsResponse) -- [cosmos/authz/v1beta1/query.proto](#cosmos/authz/v1beta1/query.proto) - - [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) - - [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) - - [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) - - [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) + - [ReflectionService](#cosmos.base.reflection.v1beta1.ReflectionService) - - [Query](#cosmos.authz.v1beta1.Query) +- [cosmos/base/snapshots/v1beta1/snapshot.proto](#cosmos/base/snapshots/v1beta1/snapshot.proto) + - [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) + - [Snapshot](#cosmos.base.snapshots.v1beta1.Snapshot) -- [cosmos/authz/v1beta1/tx.proto](#cosmos/authz/v1beta1/tx.proto) - - [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) - - [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) - - [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) - - [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) - - [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) - - [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) +- [cosmos/base/store/v1beta1/commit_info.proto](#cosmos/base/store/v1beta1/commit_info.proto) + - [CommitID](#cosmos.base.store.v1beta1.CommitID) + - [CommitInfo](#cosmos.base.store.v1beta1.CommitInfo) + - [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) - - [Msg](#cosmos.authz.v1beta1.Msg) +- [cosmos/base/store/v1beta1/snapshot.proto](#cosmos/base/store/v1beta1/snapshot.proto) + - [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) + - [SnapshotItem](#cosmos.base.store.v1beta1.SnapshotItem) + - [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) -- [cosmos/authz/v1beta1/genesis.proto](#cosmos/authz/v1beta1/genesis.proto) - - [GenesisState](#cosmos.authz.v1beta1.GenesisState) - - [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) +- [cosmos/base/tendermint/v1beta1/query.proto](#cosmos/base/tendermint/v1beta1/query.proto) + - [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) + - [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) + - [GetLatestBlockRequest](#cosmos.base.tendermint.v1beta1.GetLatestBlockRequest) + - [GetLatestBlockResponse](#cosmos.base.tendermint.v1beta1.GetLatestBlockResponse) + - [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) + - [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) + - [GetNodeInfoRequest](#cosmos.base.tendermint.v1beta1.GetNodeInfoRequest) + - [GetNodeInfoResponse](#cosmos.base.tendermint.v1beta1.GetNodeInfoResponse) + - [GetSyncingRequest](#cosmos.base.tendermint.v1beta1.GetSyncingRequest) + - [GetSyncingResponse](#cosmos.base.tendermint.v1beta1.GetSyncingResponse) + - [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) + - [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) + - [Module](#cosmos.base.tendermint.v1beta1.Module) + - [Validator](#cosmos.base.tendermint.v1beta1.Validator) + - [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) -- [cosmos/gov/v1beta1/gov.proto](#cosmos/gov/v1beta1/gov.proto) - - [Deposit](#cosmos.gov.v1beta1.Deposit) - - [DepositParams](#cosmos.gov.v1beta1.DepositParams) - - [Proposal](#cosmos.gov.v1beta1.Proposal) - - [TallyParams](#cosmos.gov.v1beta1.TallyParams) - - [TallyResult](#cosmos.gov.v1beta1.TallyResult) - - [TextProposal](#cosmos.gov.v1beta1.TextProposal) - - [Vote](#cosmos.gov.v1beta1.Vote) - - [VotingParams](#cosmos.gov.v1beta1.VotingParams) + - [Service](#cosmos.base.tendermint.v1beta1.Service) - - [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) - - [VoteOption](#cosmos.gov.v1beta1.VoteOption) +- [cosmos/capability/v1beta1/capability.proto](#cosmos/capability/v1beta1/capability.proto) + - [Capability](#cosmos.capability.v1beta1.Capability) + - [CapabilityOwners](#cosmos.capability.v1beta1.CapabilityOwners) + - [Owner](#cosmos.capability.v1beta1.Owner) -- [cosmos/gov/v1beta1/query.proto](#cosmos/gov/v1beta1/query.proto) - - [QueryDepositRequest](#cosmos.gov.v1beta1.QueryDepositRequest) - - [QueryDepositResponse](#cosmos.gov.v1beta1.QueryDepositResponse) - - [QueryDepositsRequest](#cosmos.gov.v1beta1.QueryDepositsRequest) - - [QueryDepositsResponse](#cosmos.gov.v1beta1.QueryDepositsResponse) - - [QueryParamsRequest](#cosmos.gov.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.gov.v1beta1.QueryParamsResponse) - - [QueryProposalRequest](#cosmos.gov.v1beta1.QueryProposalRequest) - - [QueryProposalResponse](#cosmos.gov.v1beta1.QueryProposalResponse) - - [QueryProposalsRequest](#cosmos.gov.v1beta1.QueryProposalsRequest) - - [QueryProposalsResponse](#cosmos.gov.v1beta1.QueryProposalsResponse) - - [QueryTallyResultRequest](#cosmos.gov.v1beta1.QueryTallyResultRequest) - - [QueryTallyResultResponse](#cosmos.gov.v1beta1.QueryTallyResultResponse) - - [QueryVoteRequest](#cosmos.gov.v1beta1.QueryVoteRequest) - - [QueryVoteResponse](#cosmos.gov.v1beta1.QueryVoteResponse) - - [QueryVotesRequest](#cosmos.gov.v1beta1.QueryVotesRequest) - - [QueryVotesResponse](#cosmos.gov.v1beta1.QueryVotesResponse) +- [cosmos/capability/v1beta1/genesis.proto](#cosmos/capability/v1beta1/genesis.proto) + - [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) + - [GenesisState](#cosmos.capability.v1beta1.GenesisState) - - [Query](#cosmos.gov.v1beta1.Query) +- [cosmos/crisis/v1beta1/genesis.proto](#cosmos/crisis/v1beta1/genesis.proto) + - [GenesisState](#cosmos.crisis.v1beta1.GenesisState) -- [cosmos/gov/v1beta1/tx.proto](#cosmos/gov/v1beta1/tx.proto) - - [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) - - [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) - - [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) - - [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) - - [MsgVote](#cosmos.gov.v1beta1.MsgVote) - - [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) +- [cosmos/crisis/v1beta1/tx.proto](#cosmos/crisis/v1beta1/tx.proto) + - [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) + - [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) - - [Msg](#cosmos.gov.v1beta1.Msg) + - [Msg](#cosmos.crisis.v1beta1.Msg) -- [cosmos/gov/v1beta1/genesis.proto](#cosmos/gov/v1beta1/genesis.proto) - - [GenesisState](#cosmos.gov.v1beta1.GenesisState) +- [cosmos/crypto/ed25519/keys.proto](#cosmos/crypto/ed25519/keys.proto) + - [PrivKey](#cosmos.crypto.ed25519.PrivKey) + - [PubKey](#cosmos.crypto.ed25519.PubKey) -- [cosmos/genutil/v1beta1/genesis.proto](#cosmos/genutil/v1beta1/genesis.proto) - - [GenesisState](#cosmos.genutil.v1beta1.GenesisState) +- [cosmos/crypto/multisig/keys.proto](#cosmos/crypto/multisig/keys.proto) + - [LegacyAminoPubKey](#cosmos.crypto.multisig.LegacyAminoPubKey) + +- [cosmos/crypto/multisig/v1beta1/multisig.proto](#cosmos/crypto/multisig/v1beta1/multisig.proto) + - [CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) + - [MultiSignature](#cosmos.crypto.multisig.v1beta1.MultiSignature) + +- [cosmos/crypto/secp256k1/keys.proto](#cosmos/crypto/secp256k1/keys.proto) + - [PrivKey](#cosmos.crypto.secp256k1.PrivKey) + - [PubKey](#cosmos.crypto.secp256k1.PubKey) + +- [cosmos/distribution/v1beta1/distribution.proto](#cosmos/distribution/v1beta1/distribution.proto) + - [CommunityPoolSpendProposal](#cosmos.distribution.v1beta1.CommunityPoolSpendProposal) + - [CommunityPoolSpendProposalWithDeposit](#cosmos.distribution.v1beta1.CommunityPoolSpendProposalWithDeposit) + - [DelegationDelegatorReward](#cosmos.distribution.v1beta1.DelegationDelegatorReward) + - [DelegatorStartingInfo](#cosmos.distribution.v1beta1.DelegatorStartingInfo) + - [FeePool](#cosmos.distribution.v1beta1.FeePool) + - [Params](#cosmos.distribution.v1beta1.Params) + - [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) + - [ValidatorCurrentRewards](#cosmos.distribution.v1beta1.ValidatorCurrentRewards) + - [ValidatorHistoricalRewards](#cosmos.distribution.v1beta1.ValidatorHistoricalRewards) + - [ValidatorOutstandingRewards](#cosmos.distribution.v1beta1.ValidatorOutstandingRewards) + - [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) + - [ValidatorSlashEvents](#cosmos.distribution.v1beta1.ValidatorSlashEvents) + +- [cosmos/distribution/v1beta1/genesis.proto](#cosmos/distribution/v1beta1/genesis.proto) + - [DelegatorStartingInfoRecord](#cosmos.distribution.v1beta1.DelegatorStartingInfoRecord) + - [DelegatorWithdrawInfo](#cosmos.distribution.v1beta1.DelegatorWithdrawInfo) + - [GenesisState](#cosmos.distribution.v1beta1.GenesisState) + - [ValidatorAccumulatedCommissionRecord](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommissionRecord) + - [ValidatorCurrentRewardsRecord](#cosmos.distribution.v1beta1.ValidatorCurrentRewardsRecord) + - [ValidatorHistoricalRewardsRecord](#cosmos.distribution.v1beta1.ValidatorHistoricalRewardsRecord) + - [ValidatorOutstandingRewardsRecord](#cosmos.distribution.v1beta1.ValidatorOutstandingRewardsRecord) + - [ValidatorSlashEventRecord](#cosmos.distribution.v1beta1.ValidatorSlashEventRecord) - [cosmos/distribution/v1beta1/query.proto](#cosmos/distribution/v1beta1/query.proto) - [QueryCommunityPoolRequest](#cosmos.distribution.v1beta1.QueryCommunityPoolRequest) @@ -264,116 +244,138 @@ - [Msg](#cosmos.distribution.v1beta1.Msg) -- [cosmos/distribution/v1beta1/genesis.proto](#cosmos/distribution/v1beta1/genesis.proto) - - [DelegatorStartingInfoRecord](#cosmos.distribution.v1beta1.DelegatorStartingInfoRecord) - - [DelegatorWithdrawInfo](#cosmos.distribution.v1beta1.DelegatorWithdrawInfo) - - [GenesisState](#cosmos.distribution.v1beta1.GenesisState) - - [ValidatorAccumulatedCommissionRecord](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommissionRecord) - - [ValidatorCurrentRewardsRecord](#cosmos.distribution.v1beta1.ValidatorCurrentRewardsRecord) - - [ValidatorHistoricalRewardsRecord](#cosmos.distribution.v1beta1.ValidatorHistoricalRewardsRecord) - - [ValidatorOutstandingRewardsRecord](#cosmos.distribution.v1beta1.ValidatorOutstandingRewardsRecord) - - [ValidatorSlashEventRecord](#cosmos.distribution.v1beta1.ValidatorSlashEventRecord) +- [cosmos/evidence/v1beta1/evidence.proto](#cosmos/evidence/v1beta1/evidence.proto) + - [Equivocation](#cosmos.evidence.v1beta1.Equivocation) -- [cosmos/distribution/v1beta1/distribution.proto](#cosmos/distribution/v1beta1/distribution.proto) - - [CommunityPoolSpendProposal](#cosmos.distribution.v1beta1.CommunityPoolSpendProposal) - - [CommunityPoolSpendProposalWithDeposit](#cosmos.distribution.v1beta1.CommunityPoolSpendProposalWithDeposit) - - [DelegationDelegatorReward](#cosmos.distribution.v1beta1.DelegationDelegatorReward) - - [DelegatorStartingInfo](#cosmos.distribution.v1beta1.DelegatorStartingInfo) - - [FeePool](#cosmos.distribution.v1beta1.FeePool) - - [Params](#cosmos.distribution.v1beta1.Params) - - [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) - - [ValidatorCurrentRewards](#cosmos.distribution.v1beta1.ValidatorCurrentRewards) - - [ValidatorHistoricalRewards](#cosmos.distribution.v1beta1.ValidatorHistoricalRewards) - - [ValidatorOutstandingRewards](#cosmos.distribution.v1beta1.ValidatorOutstandingRewards) - - [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) - - [ValidatorSlashEvents](#cosmos.distribution.v1beta1.ValidatorSlashEvents) +- [cosmos/evidence/v1beta1/genesis.proto](#cosmos/evidence/v1beta1/genesis.proto) + - [GenesisState](#cosmos.evidence.v1beta1.GenesisState) -- [cosmos/upgrade/v1beta1/query.proto](#cosmos/upgrade/v1beta1/query.proto) - - [QueryAppliedPlanRequest](#cosmos.upgrade.v1beta1.QueryAppliedPlanRequest) - - [QueryAppliedPlanResponse](#cosmos.upgrade.v1beta1.QueryAppliedPlanResponse) - - [QueryCurrentPlanRequest](#cosmos.upgrade.v1beta1.QueryCurrentPlanRequest) - - [QueryCurrentPlanResponse](#cosmos.upgrade.v1beta1.QueryCurrentPlanResponse) - - [QueryUpgradedConsensusStateRequest](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateRequest) - - [QueryUpgradedConsensusStateResponse](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse) +- [cosmos/evidence/v1beta1/query.proto](#cosmos/evidence/v1beta1/query.proto) + - [QueryAllEvidenceRequest](#cosmos.evidence.v1beta1.QueryAllEvidenceRequest) + - [QueryAllEvidenceResponse](#cosmos.evidence.v1beta1.QueryAllEvidenceResponse) + - [QueryEvidenceRequest](#cosmos.evidence.v1beta1.QueryEvidenceRequest) + - [QueryEvidenceResponse](#cosmos.evidence.v1beta1.QueryEvidenceResponse) - - [Query](#cosmos.upgrade.v1beta1.Query) + - [Query](#cosmos.evidence.v1beta1.Query) -- [cosmos/upgrade/v1beta1/upgrade.proto](#cosmos/upgrade/v1beta1/upgrade.proto) - - [CancelSoftwareUpgradeProposal](#cosmos.upgrade.v1beta1.CancelSoftwareUpgradeProposal) - - [Plan](#cosmos.upgrade.v1beta1.Plan) - - [SoftwareUpgradeProposal](#cosmos.upgrade.v1beta1.SoftwareUpgradeProposal) +- [cosmos/evidence/v1beta1/tx.proto](#cosmos/evidence/v1beta1/tx.proto) + - [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) + - [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) -- [cosmos/base/kv/v1beta1/kv.proto](#cosmos/base/kv/v1beta1/kv.proto) - - [Pair](#cosmos.base.kv.v1beta1.Pair) - - [Pairs](#cosmos.base.kv.v1beta1.Pairs) + - [Msg](#cosmos.evidence.v1beta1.Msg) -- [cosmos/base/abci/v1beta1/abci.proto](#cosmos/base/abci/v1beta1/abci.proto) - - [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) - - [Attribute](#cosmos.base.abci.v1beta1.Attribute) - - [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) - - [MsgData](#cosmos.base.abci.v1beta1.MsgData) - - [Result](#cosmos.base.abci.v1beta1.Result) - - [SearchTxsResult](#cosmos.base.abci.v1beta1.SearchTxsResult) - - [SimulationResponse](#cosmos.base.abci.v1beta1.SimulationResponse) - - [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) - - [TxMsgData](#cosmos.base.abci.v1beta1.TxMsgData) - - [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) +- [cosmos/feegrant/v1beta1/feegrant.proto](#cosmos/feegrant/v1beta1/feegrant.proto) + - [BasicFeeAllowance](#cosmos.feegrant.v1beta1.BasicFeeAllowance) + - [Duration](#cosmos.feegrant.v1beta1.Duration) + - [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) + - [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) + - [PeriodicFeeAllowance](#cosmos.feegrant.v1beta1.PeriodicFeeAllowance) -- [cosmos/base/query/v1beta1/pagination.proto](#cosmos/base/query/v1beta1/pagination.proto) - - [PageRequest](#cosmos.base.query.v1beta1.PageRequest) - - [PageResponse](#cosmos.base.query.v1beta1.PageResponse) +- [cosmos/feegrant/v1beta1/genesis.proto](#cosmos/feegrant/v1beta1/genesis.proto) + - [GenesisState](#cosmos.feegrant.v1beta1.GenesisState) -- [cosmos/base/store/v1beta1/snapshot.proto](#cosmos/base/store/v1beta1/snapshot.proto) - - [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) - - [SnapshotItem](#cosmos.base.store.v1beta1.SnapshotItem) - - [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) +- [cosmos/feegrant/v1beta1/query.proto](#cosmos/feegrant/v1beta1/query.proto) + - [QueryFeeAllowanceRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowanceRequest) + - [QueryFeeAllowanceResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowanceResponse) + - [QueryFeeAllowancesRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowancesRequest) + - [QueryFeeAllowancesResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowancesResponse) -- [cosmos/base/store/v1beta1/commit_info.proto](#cosmos/base/store/v1beta1/commit_info.proto) - - [CommitID](#cosmos.base.store.v1beta1.CommitID) - - [CommitInfo](#cosmos.base.store.v1beta1.CommitInfo) - - [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) + - [Query](#cosmos.feegrant.v1beta1.Query) + +- [cosmos/feegrant/v1beta1/tx.proto](#cosmos/feegrant/v1beta1/tx.proto) + - [MsgGrantFeeAllowance](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowance) + - [MsgGrantFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowanceResponse) + - [MsgRevokeFeeAllowance](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowance) + - [MsgRevokeFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowanceResponse) + + - [Msg](#cosmos.feegrant.v1beta1.Msg) + +- [cosmos/genutil/v1beta1/genesis.proto](#cosmos/genutil/v1beta1/genesis.proto) + - [GenesisState](#cosmos.genutil.v1beta1.GenesisState) + +- [cosmos/gov/v1beta1/gov.proto](#cosmos/gov/v1beta1/gov.proto) + - [Deposit](#cosmos.gov.v1beta1.Deposit) + - [DepositParams](#cosmos.gov.v1beta1.DepositParams) + - [Proposal](#cosmos.gov.v1beta1.Proposal) + - [TallyParams](#cosmos.gov.v1beta1.TallyParams) + - [TallyResult](#cosmos.gov.v1beta1.TallyResult) + - [TextProposal](#cosmos.gov.v1beta1.TextProposal) + - [Vote](#cosmos.gov.v1beta1.Vote) + - [VotingParams](#cosmos.gov.v1beta1.VotingParams) + + - [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) + - [VoteOption](#cosmos.gov.v1beta1.VoteOption) + +- [cosmos/gov/v1beta1/genesis.proto](#cosmos/gov/v1beta1/genesis.proto) + - [GenesisState](#cosmos.gov.v1beta1.GenesisState) + +- [cosmos/gov/v1beta1/query.proto](#cosmos/gov/v1beta1/query.proto) + - [QueryDepositRequest](#cosmos.gov.v1beta1.QueryDepositRequest) + - [QueryDepositResponse](#cosmos.gov.v1beta1.QueryDepositResponse) + - [QueryDepositsRequest](#cosmos.gov.v1beta1.QueryDepositsRequest) + - [QueryDepositsResponse](#cosmos.gov.v1beta1.QueryDepositsResponse) + - [QueryParamsRequest](#cosmos.gov.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.gov.v1beta1.QueryParamsResponse) + - [QueryProposalRequest](#cosmos.gov.v1beta1.QueryProposalRequest) + - [QueryProposalResponse](#cosmos.gov.v1beta1.QueryProposalResponse) + - [QueryProposalsRequest](#cosmos.gov.v1beta1.QueryProposalsRequest) + - [QueryProposalsResponse](#cosmos.gov.v1beta1.QueryProposalsResponse) + - [QueryTallyResultRequest](#cosmos.gov.v1beta1.QueryTallyResultRequest) + - [QueryTallyResultResponse](#cosmos.gov.v1beta1.QueryTallyResultResponse) + - [QueryVoteRequest](#cosmos.gov.v1beta1.QueryVoteRequest) + - [QueryVoteResponse](#cosmos.gov.v1beta1.QueryVoteResponse) + - [QueryVotesRequest](#cosmos.gov.v1beta1.QueryVotesRequest) + - [QueryVotesResponse](#cosmos.gov.v1beta1.QueryVotesResponse) + + - [Query](#cosmos.gov.v1beta1.Query) + +- [cosmos/gov/v1beta1/tx.proto](#cosmos/gov/v1beta1/tx.proto) + - [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) + - [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) + - [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) + - [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) + - [MsgVote](#cosmos.gov.v1beta1.MsgVote) + - [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) + + - [Msg](#cosmos.gov.v1beta1.Msg) -- [cosmos/base/v1beta1/coin.proto](#cosmos/base/v1beta1/coin.proto) - - [Coin](#cosmos.base.v1beta1.Coin) - - [DecCoin](#cosmos.base.v1beta1.DecCoin) - - [DecProto](#cosmos.base.v1beta1.DecProto) - - [IntProto](#cosmos.base.v1beta1.IntProto) +- [cosmos/mint/v1beta1/mint.proto](#cosmos/mint/v1beta1/mint.proto) + - [Minter](#cosmos.mint.v1beta1.Minter) + - [Params](#cosmos.mint.v1beta1.Params) -- [cosmos/base/tendermint/v1beta1/query.proto](#cosmos/base/tendermint/v1beta1/query.proto) - - [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) - - [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) - - [GetLatestBlockRequest](#cosmos.base.tendermint.v1beta1.GetLatestBlockRequest) - - [GetLatestBlockResponse](#cosmos.base.tendermint.v1beta1.GetLatestBlockResponse) - - [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) - - [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) - - [GetNodeInfoRequest](#cosmos.base.tendermint.v1beta1.GetNodeInfoRequest) - - [GetNodeInfoResponse](#cosmos.base.tendermint.v1beta1.GetNodeInfoResponse) - - [GetSyncingRequest](#cosmos.base.tendermint.v1beta1.GetSyncingRequest) - - [GetSyncingResponse](#cosmos.base.tendermint.v1beta1.GetSyncingResponse) - - [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) - - [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) - - [Module](#cosmos.base.tendermint.v1beta1.Module) - - [Validator](#cosmos.base.tendermint.v1beta1.Validator) - - [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) +- [cosmos/mint/v1beta1/genesis.proto](#cosmos/mint/v1beta1/genesis.proto) + - [GenesisState](#cosmos.mint.v1beta1.GenesisState) - - [Service](#cosmos.base.tendermint.v1beta1.Service) +- [cosmos/mint/v1beta1/query.proto](#cosmos/mint/v1beta1/query.proto) + - [QueryAnnualProvisionsRequest](#cosmos.mint.v1beta1.QueryAnnualProvisionsRequest) + - [QueryAnnualProvisionsResponse](#cosmos.mint.v1beta1.QueryAnnualProvisionsResponse) + - [QueryInflationRequest](#cosmos.mint.v1beta1.QueryInflationRequest) + - [QueryInflationResponse](#cosmos.mint.v1beta1.QueryInflationResponse) + - [QueryParamsRequest](#cosmos.mint.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.mint.v1beta1.QueryParamsResponse) -- [cosmos/base/snapshots/v1beta1/snapshot.proto](#cosmos/base/snapshots/v1beta1/snapshot.proto) - - [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) - - [Snapshot](#cosmos.base.snapshots.v1beta1.Snapshot) + - [Query](#cosmos.mint.v1beta1.Query) -- [cosmos/base/reflection/v1beta1/reflection.proto](#cosmos/base/reflection/v1beta1/reflection.proto) - - [ListAllInterfacesRequest](#cosmos.base.reflection.v1beta1.ListAllInterfacesRequest) - - [ListAllInterfacesResponse](#cosmos.base.reflection.v1beta1.ListAllInterfacesResponse) - - [ListImplementationsRequest](#cosmos.base.reflection.v1beta1.ListImplementationsRequest) - - [ListImplementationsResponse](#cosmos.base.reflection.v1beta1.ListImplementationsResponse) +- [cosmos/params/v1beta1/params.proto](#cosmos/params/v1beta1/params.proto) + - [ParamChange](#cosmos.params.v1beta1.ParamChange) + - [ParameterChangeProposal](#cosmos.params.v1beta1.ParameterChangeProposal) - - [ReflectionService](#cosmos.base.reflection.v1beta1.ReflectionService) +- [cosmos/params/v1beta1/query.proto](#cosmos/params/v1beta1/query.proto) + - [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) + + - [Query](#cosmos.params.v1beta1.Query) - [cosmos/slashing/v1beta1/slashing.proto](#cosmos/slashing/v1beta1/slashing.proto) - [Params](#cosmos.slashing.v1beta1.Params) - [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) +- [cosmos/slashing/v1beta1/genesis.proto](#cosmos/slashing/v1beta1/genesis.proto) + - [GenesisState](#cosmos.slashing.v1beta1.GenesisState) + - [MissedBlock](#cosmos.slashing.v1beta1.MissedBlock) + - [SigningInfo](#cosmos.slashing.v1beta1.SigningInfo) + - [ValidatorMissedBlocks](#cosmos.slashing.v1beta1.ValidatorMissedBlocks) + - [cosmos/slashing/v1beta1/query.proto](#cosmos/slashing/v1beta1/query.proto) - [QueryParamsRequest](#cosmos.slashing.v1beta1.QueryParamsRequest) - [QueryParamsResponse](#cosmos.slashing.v1beta1.QueryParamsResponse) @@ -390,47 +392,33 @@ - [Msg](#cosmos.slashing.v1beta1.Msg) -- [cosmos/slashing/v1beta1/genesis.proto](#cosmos/slashing/v1beta1/genesis.proto) - - [GenesisState](#cosmos.slashing.v1beta1.GenesisState) - - [MissedBlock](#cosmos.slashing.v1beta1.MissedBlock) - - [SigningInfo](#cosmos.slashing.v1beta1.SigningInfo) - - [ValidatorMissedBlocks](#cosmos.slashing.v1beta1.ValidatorMissedBlocks) - -- [cosmos/evidence/v1beta1/evidence.proto](#cosmos/evidence/v1beta1/evidence.proto) - - [Equivocation](#cosmos.evidence.v1beta1.Equivocation) - -- [cosmos/evidence/v1beta1/query.proto](#cosmos/evidence/v1beta1/query.proto) - - [QueryAllEvidenceRequest](#cosmos.evidence.v1beta1.QueryAllEvidenceRequest) - - [QueryAllEvidenceResponse](#cosmos.evidence.v1beta1.QueryAllEvidenceResponse) - - [QueryEvidenceRequest](#cosmos.evidence.v1beta1.QueryEvidenceRequest) - - [QueryEvidenceResponse](#cosmos.evidence.v1beta1.QueryEvidenceResponse) - - - [Query](#cosmos.evidence.v1beta1.Query) - -- [cosmos/evidence/v1beta1/tx.proto](#cosmos/evidence/v1beta1/tx.proto) - - [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) - - [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) - - - [Msg](#cosmos.evidence.v1beta1.Msg) - -- [cosmos/evidence/v1beta1/genesis.proto](#cosmos/evidence/v1beta1/genesis.proto) - - [GenesisState](#cosmos.evidence.v1beta1.GenesisState) - -- [cosmos/auth/v1beta1/auth.proto](#cosmos/auth/v1beta1/auth.proto) - - [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) - - [ModuleAccount](#cosmos.auth.v1beta1.ModuleAccount) - - [Params](#cosmos.auth.v1beta1.Params) - -- [cosmos/auth/v1beta1/query.proto](#cosmos/auth/v1beta1/query.proto) - - [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) - - [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) - - [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) +- [cosmos/staking/v1beta1/staking.proto](#cosmos/staking/v1beta1/staking.proto) + - [Commission](#cosmos.staking.v1beta1.Commission) + - [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) + - [DVPair](#cosmos.staking.v1beta1.DVPair) + - [DVPairs](#cosmos.staking.v1beta1.DVPairs) + - [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) + - [DVVTriplets](#cosmos.staking.v1beta1.DVVTriplets) + - [Delegation](#cosmos.staking.v1beta1.Delegation) + - [DelegationResponse](#cosmos.staking.v1beta1.DelegationResponse) + - [Description](#cosmos.staking.v1beta1.Description) + - [HistoricalInfo](#cosmos.staking.v1beta1.HistoricalInfo) + - [Params](#cosmos.staking.v1beta1.Params) + - [Pool](#cosmos.staking.v1beta1.Pool) + - [Redelegation](#cosmos.staking.v1beta1.Redelegation) + - [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) + - [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) + - [RedelegationResponse](#cosmos.staking.v1beta1.RedelegationResponse) + - [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) + - [UnbondingDelegationEntry](#cosmos.staking.v1beta1.UnbondingDelegationEntry) + - [ValAddresses](#cosmos.staking.v1beta1.ValAddresses) + - [Validator](#cosmos.staking.v1beta1.Validator) - - [Query](#cosmos.auth.v1beta1.Query) + - [BondStatus](#cosmos.staking.v1beta1.BondStatus) -- [cosmos/auth/v1beta1/genesis.proto](#cosmos/auth/v1beta1/genesis.proto) - - [GenesisState](#cosmos.auth.v1beta1.GenesisState) +- [cosmos/staking/v1beta1/genesis.proto](#cosmos/staking/v1beta1/genesis.proto) + - [GenesisState](#cosmos.staking.v1beta1.GenesisState) + - [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) - [cosmos/staking/v1beta1/query.proto](#cosmos/staking/v1beta1/query.proto) - [QueryDelegationRequest](#cosmos.staking.v1beta1.QueryDelegationRequest) @@ -478,33 +466,55 @@ - [Msg](#cosmos.staking.v1beta1.Msg) -- [cosmos/staking/v1beta1/genesis.proto](#cosmos/staking/v1beta1/genesis.proto) - - [GenesisState](#cosmos.staking.v1beta1.GenesisState) - - [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) +- [cosmos/tx/signing/v1beta1/signing.proto](#cosmos/tx/signing/v1beta1/signing.proto) + - [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) + - [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) + - [SignatureDescriptor.Data.Multi](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Multi) + - [SignatureDescriptor.Data.Single](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Single) + - [SignatureDescriptors](#cosmos.tx.signing.v1beta1.SignatureDescriptors) -- [cosmos/staking/v1beta1/staking.proto](#cosmos/staking/v1beta1/staking.proto) - - [Commission](#cosmos.staking.v1beta1.Commission) - - [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) - - [DVPair](#cosmos.staking.v1beta1.DVPair) - - [DVPairs](#cosmos.staking.v1beta1.DVPairs) - - [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) - - [DVVTriplets](#cosmos.staking.v1beta1.DVVTriplets) - - [Delegation](#cosmos.staking.v1beta1.Delegation) - - [DelegationResponse](#cosmos.staking.v1beta1.DelegationResponse) - - [Description](#cosmos.staking.v1beta1.Description) - - [HistoricalInfo](#cosmos.staking.v1beta1.HistoricalInfo) - - [Params](#cosmos.staking.v1beta1.Params) - - [Pool](#cosmos.staking.v1beta1.Pool) - - [Redelegation](#cosmos.staking.v1beta1.Redelegation) - - [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) - - [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) - - [RedelegationResponse](#cosmos.staking.v1beta1.RedelegationResponse) - - [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) - - [UnbondingDelegationEntry](#cosmos.staking.v1beta1.UnbondingDelegationEntry) - - [ValAddresses](#cosmos.staking.v1beta1.ValAddresses) - - [Validator](#cosmos.staking.v1beta1.Validator) + - [SignMode](#cosmos.tx.signing.v1beta1.SignMode) - - [BondStatus](#cosmos.staking.v1beta1.BondStatus) +- [cosmos/tx/v1beta1/tx.proto](#cosmos/tx/v1beta1/tx.proto) + - [AuthInfo](#cosmos.tx.v1beta1.AuthInfo) + - [Fee](#cosmos.tx.v1beta1.Fee) + - [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) + - [ModeInfo.Multi](#cosmos.tx.v1beta1.ModeInfo.Multi) + - [ModeInfo.Single](#cosmos.tx.v1beta1.ModeInfo.Single) + - [SignDoc](#cosmos.tx.v1beta1.SignDoc) + - [SignerInfo](#cosmos.tx.v1beta1.SignerInfo) + - [Tx](#cosmos.tx.v1beta1.Tx) + - [TxBody](#cosmos.tx.v1beta1.TxBody) + - [TxRaw](#cosmos.tx.v1beta1.TxRaw) + +- [cosmos/tx/v1beta1/service.proto](#cosmos/tx/v1beta1/service.proto) + - [BroadcastTxRequest](#cosmos.tx.v1beta1.BroadcastTxRequest) + - [BroadcastTxResponse](#cosmos.tx.v1beta1.BroadcastTxResponse) + - [GetTxRequest](#cosmos.tx.v1beta1.GetTxRequest) + - [GetTxResponse](#cosmos.tx.v1beta1.GetTxResponse) + - [GetTxsEventRequest](#cosmos.tx.v1beta1.GetTxsEventRequest) + - [GetTxsEventResponse](#cosmos.tx.v1beta1.GetTxsEventResponse) + - [SimulateRequest](#cosmos.tx.v1beta1.SimulateRequest) + - [SimulateResponse](#cosmos.tx.v1beta1.SimulateResponse) + + - [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) + + - [Service](#cosmos.tx.v1beta1.Service) + +- [cosmos/upgrade/v1beta1/upgrade.proto](#cosmos/upgrade/v1beta1/upgrade.proto) + - [CancelSoftwareUpgradeProposal](#cosmos.upgrade.v1beta1.CancelSoftwareUpgradeProposal) + - [Plan](#cosmos.upgrade.v1beta1.Plan) + - [SoftwareUpgradeProposal](#cosmos.upgrade.v1beta1.SoftwareUpgradeProposal) + +- [cosmos/upgrade/v1beta1/query.proto](#cosmos/upgrade/v1beta1/query.proto) + - [QueryAppliedPlanRequest](#cosmos.upgrade.v1beta1.QueryAppliedPlanRequest) + - [QueryAppliedPlanResponse](#cosmos.upgrade.v1beta1.QueryAppliedPlanResponse) + - [QueryCurrentPlanRequest](#cosmos.upgrade.v1beta1.QueryCurrentPlanRequest) + - [QueryCurrentPlanResponse](#cosmos.upgrade.v1beta1.QueryCurrentPlanResponse) + - [QueryUpgradedConsensusStateRequest](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateRequest) + - [QueryUpgradedConsensusStateResponse](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse) + + - [Query](#cosmos.upgrade.v1beta1.Query) - [cosmos/vesting/v1beta1/tx.proto](#cosmos/vesting/v1beta1/tx.proto) - [MsgCreateVestingAccount](#cosmos.vesting.v1beta1.MsgCreateVestingAccount) @@ -519,15 +529,13 @@ - [Period](#cosmos.vesting.v1beta1.Period) - [PeriodicVestingAccount](#cosmos.vesting.v1beta1.PeriodicVestingAccount) -- [cosmos/params/v1beta1/query.proto](#cosmos/params/v1beta1/query.proto) - - [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) - - - [Query](#cosmos.params.v1beta1.Query) +- [ibc/applications/transfer/v1/transfer.proto](#ibc/applications/transfer/v1/transfer.proto) + - [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) + - [FungibleTokenPacketData](#ibc.applications.transfer.v1.FungibleTokenPacketData) + - [Params](#ibc.applications.transfer.v1.Params) -- [cosmos/params/v1beta1/params.proto](#cosmos/params/v1beta1/params.proto) - - [ParamChange](#cosmos.params.v1beta1.ParamChange) - - [ParameterChangeProposal](#cosmos.params.v1beta1.ParameterChangeProposal) +- [ibc/applications/transfer/v1/genesis.proto](#ibc/applications/transfer/v1/genesis.proto) + - [GenesisState](#ibc.applications.transfer.v1.GenesisState) - [ibc/applications/transfer/v1/query.proto](#ibc/applications/transfer/v1/query.proto) - [QueryDenomTraceRequest](#ibc.applications.transfer.v1.QueryDenomTraceRequest) @@ -537,60 +545,21 @@ - [QueryParamsRequest](#ibc.applications.transfer.v1.QueryParamsRequest) - [QueryParamsResponse](#ibc.applications.transfer.v1.QueryParamsResponse) - - [Query](#ibc.applications.transfer.v1.Query) - -- [ibc/applications/transfer/v1/tx.proto](#ibc/applications/transfer/v1/tx.proto) - - [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) - - [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) - - - [Msg](#ibc.applications.transfer.v1.Msg) - -- [ibc/applications/transfer/v1/transfer.proto](#ibc/applications/transfer/v1/transfer.proto) - - [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) - - [FungibleTokenPacketData](#ibc.applications.transfer.v1.FungibleTokenPacketData) - - [Params](#ibc.applications.transfer.v1.Params) - -- [ibc/applications/transfer/v1/genesis.proto](#ibc/applications/transfer/v1/genesis.proto) - - [GenesisState](#ibc.applications.transfer.v1.GenesisState) - -- [ibc/core/client/v1/client.proto](#ibc/core/client/v1/client.proto) - - [ClientConsensusStates](#ibc.core.client.v1.ClientConsensusStates) - - [ClientUpdateProposal](#ibc.core.client.v1.ClientUpdateProposal) - - [ConsensusStateWithHeight](#ibc.core.client.v1.ConsensusStateWithHeight) - - [Height](#ibc.core.client.v1.Height) - - [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) - - [Params](#ibc.core.client.v1.Params) - -- [ibc/core/client/v1/query.proto](#ibc/core/client/v1/query.proto) - - [QueryClientParamsRequest](#ibc.core.client.v1.QueryClientParamsRequest) - - [QueryClientParamsResponse](#ibc.core.client.v1.QueryClientParamsResponse) - - [QueryClientStateRequest](#ibc.core.client.v1.QueryClientStateRequest) - - [QueryClientStateResponse](#ibc.core.client.v1.QueryClientStateResponse) - - [QueryClientStatesRequest](#ibc.core.client.v1.QueryClientStatesRequest) - - [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse) - - [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest) - - [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) - - [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) - - [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) - - - [Query](#ibc.core.client.v1.Query) - -- [ibc/core/client/v1/tx.proto](#ibc/core/client/v1/tx.proto) - - [MsgCreateClient](#ibc.core.client.v1.MsgCreateClient) - - [MsgCreateClientResponse](#ibc.core.client.v1.MsgCreateClientResponse) - - [MsgSubmitMisbehaviour](#ibc.core.client.v1.MsgSubmitMisbehaviour) - - [MsgSubmitMisbehaviourResponse](#ibc.core.client.v1.MsgSubmitMisbehaviourResponse) - - [MsgUpdateClient](#ibc.core.client.v1.MsgUpdateClient) - - [MsgUpdateClientResponse](#ibc.core.client.v1.MsgUpdateClientResponse) - - [MsgUpgradeClient](#ibc.core.client.v1.MsgUpgradeClient) - - [MsgUpgradeClientResponse](#ibc.core.client.v1.MsgUpgradeClientResponse) + - [Query](#ibc.applications.transfer.v1.Query) - - [Msg](#ibc.core.client.v1.Msg) +- [ibc/core/client/v1/client.proto](#ibc/core/client/v1/client.proto) + - [ClientConsensusStates](#ibc.core.client.v1.ClientConsensusStates) + - [ClientUpdateProposal](#ibc.core.client.v1.ClientUpdateProposal) + - [ConsensusStateWithHeight](#ibc.core.client.v1.ConsensusStateWithHeight) + - [Height](#ibc.core.client.v1.Height) + - [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) + - [Params](#ibc.core.client.v1.Params) -- [ibc/core/client/v1/genesis.proto](#ibc/core/client/v1/genesis.proto) - - [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) - - [GenesisState](#ibc.core.client.v1.GenesisState) - - [IdentifiedGenesisMetadata](#ibc.core.client.v1.IdentifiedGenesisMetadata) +- [ibc/applications/transfer/v1/tx.proto](#ibc/applications/transfer/v1/tx.proto) + - [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) + - [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) + + - [Msg](#ibc.applications.transfer.v1.Msg) - [ibc/core/channel/v1/channel.proto](#ibc/core/channel/v1/channel.proto) - [Acknowledgement](#ibc.core.channel.v1.Acknowledgement) @@ -603,6 +572,10 @@ - [Order](#ibc.core.channel.v1.Order) - [State](#ibc.core.channel.v1.State) +- [ibc/core/channel/v1/genesis.proto](#ibc/core/channel/v1/genesis.proto) + - [GenesisState](#ibc.core.channel.v1.GenesisState) + - [PacketSequence](#ibc.core.channel.v1.PacketSequence) + - [ibc/core/channel/v1/query.proto](#ibc/core/channel/v1/query.proto) - [QueryChannelClientStateRequest](#ibc.core.channel.v1.QueryChannelClientStateRequest) - [QueryChannelClientStateResponse](#ibc.core.channel.v1.QueryChannelClientStateResponse) @@ -657,9 +630,36 @@ - [Msg](#ibc.core.channel.v1.Msg) -- [ibc/core/channel/v1/genesis.proto](#ibc/core/channel/v1/genesis.proto) - - [GenesisState](#ibc.core.channel.v1.GenesisState) - - [PacketSequence](#ibc.core.channel.v1.PacketSequence) +- [ibc/core/client/v1/genesis.proto](#ibc/core/client/v1/genesis.proto) + - [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) + - [GenesisState](#ibc.core.client.v1.GenesisState) + - [IdentifiedGenesisMetadata](#ibc.core.client.v1.IdentifiedGenesisMetadata) + +- [ibc/core/client/v1/query.proto](#ibc/core/client/v1/query.proto) + - [QueryClientParamsRequest](#ibc.core.client.v1.QueryClientParamsRequest) + - [QueryClientParamsResponse](#ibc.core.client.v1.QueryClientParamsResponse) + - [QueryClientStateRequest](#ibc.core.client.v1.QueryClientStateRequest) + - [QueryClientStateResponse](#ibc.core.client.v1.QueryClientStateResponse) + - [QueryClientStatesRequest](#ibc.core.client.v1.QueryClientStatesRequest) + - [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse) + - [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest) + - [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) + - [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) + - [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) + + - [Query](#ibc.core.client.v1.Query) + +- [ibc/core/client/v1/tx.proto](#ibc/core/client/v1/tx.proto) + - [MsgCreateClient](#ibc.core.client.v1.MsgCreateClient) + - [MsgCreateClientResponse](#ibc.core.client.v1.MsgCreateClientResponse) + - [MsgSubmitMisbehaviour](#ibc.core.client.v1.MsgSubmitMisbehaviour) + - [MsgSubmitMisbehaviourResponse](#ibc.core.client.v1.MsgSubmitMisbehaviourResponse) + - [MsgUpdateClient](#ibc.core.client.v1.MsgUpdateClient) + - [MsgUpdateClientResponse](#ibc.core.client.v1.MsgUpdateClientResponse) + - [MsgUpgradeClient](#ibc.core.client.v1.MsgUpgradeClient) + - [MsgUpgradeClientResponse](#ibc.core.client.v1.MsgUpgradeClientResponse) + + - [Msg](#ibc.core.client.v1.Msg) - [ibc/core/commitment/v1/commitment.proto](#ibc/core/commitment/v1/commitment.proto) - [MerklePath](#ibc.core.commitment.v1.MerklePath) @@ -677,6 +677,9 @@ - [State](#ibc.core.connection.v1.State) +- [ibc/core/connection/v1/genesis.proto](#ibc/core/connection/v1/genesis.proto) + - [GenesisState](#ibc.core.connection.v1.GenesisState) + - [ibc/core/connection/v1/query.proto](#ibc/core/connection/v1/query.proto) - [QueryClientConnectionsRequest](#ibc.core.connection.v1.QueryClientConnectionsRequest) - [QueryClientConnectionsResponse](#ibc.core.connection.v1.QueryClientConnectionsResponse) @@ -703,22 +706,12 @@ - [Msg](#ibc.core.connection.v1.Msg) -- [ibc/core/connection/v1/genesis.proto](#ibc/core/connection/v1/genesis.proto) - - [GenesisState](#ibc.core.connection.v1.GenesisState) - - [ibc/core/types/v1/genesis.proto](#ibc/core/types/v1/genesis.proto) - [GenesisState](#ibc.core.types.v1.GenesisState) - [ibc/lightclients/localhost/v1/localhost.proto](#ibc/lightclients/localhost/v1/localhost.proto) - [ClientState](#ibc.lightclients.localhost.v1.ClientState) -- [ibc/lightclients/tendermint/v1/tendermint.proto](#ibc/lightclients/tendermint/v1/tendermint.proto) - - [ClientState](#ibc.lightclients.tendermint.v1.ClientState) - - [ConsensusState](#ibc.lightclients.tendermint.v1.ConsensusState) - - [Fraction](#ibc.lightclients.tendermint.v1.Fraction) - - [Header](#ibc.lightclients.tendermint.v1.Header) - - [Misbehaviour](#ibc.lightclients.tendermint.v1.Misbehaviour) - - [ibc/lightclients/solomachine/v1/solomachine.proto](#ibc/lightclients/solomachine/v1/solomachine.proto) - [ChannelStateData](#ibc.lightclients.solomachine.v1.ChannelStateData) - [ClientState](#ibc.lightclients.solomachine.v1.ClientState) @@ -739,190 +732,106 @@ - [DataType](#ibc.lightclients.solomachine.v1.DataType) +- [ibc/lightclients/tendermint/v1/tendermint.proto](#ibc/lightclients/tendermint/v1/tendermint.proto) + - [ClientState](#ibc.lightclients.tendermint.v1.ClientState) + - [ConsensusState](#ibc.lightclients.tendermint.v1.ConsensusState) + - [Fraction](#ibc.lightclients.tendermint.v1.Fraction) + - [Header](#ibc.lightclients.tendermint.v1.Header) + - [Misbehaviour](#ibc.lightclients.tendermint.v1.Misbehaviour) + - [Scalar Value Types](#scalar-value-types) - +

      Top

      -## cosmos/tx/v1beta1/tx.proto - - - - - -### AuthInfo -AuthInfo describes the fee and signer modes that are used to sign a -transaction. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `signer_infos` | [SignerInfo](#cosmos.tx.v1beta1.SignerInfo) | repeated | signer_infos defines the signing modes for the required signers. The number and order of elements must match the required signers from TxBody's messages. The first element is the primary signer and the one which pays the fee. | -| `fee` | [Fee](#cosmos.tx.v1beta1.Fee) | | Fee is the fee and gas limit for the transaction. The first signer is the primary signer and the one which pays the fee. The fee can be calculated based on the cost of evaluating the body and doing signature verification of the signers. This can be estimated via simulation. | - - - - - - - - -### Fee -Fee includes the amount of coins paid in fees and the maximum -gas to be used by the transaction. The ratio yields an effective "gasprice", -which must be above some miminum to be accepted into the mempool. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | amount is the amount of coins to be paid as a fee | -| `gas_limit` | [uint64](#uint64) | | gas_limit is the maximum gas that can be used in transaction processing before an out of gas error occurs | -| `payer` | [string](#string) | | if unset, the first signer is responsible for paying the fees. If set, the specified account must pay the fees. the payer must be a tx signer (and thus have signed this field in AuthInfo). setting this field does *not* change the ordering of required signers for the transaction. | -| `granter` | [string](#string) | | if set, the fee payer (either the first signer or the value of the payer field) requests that a fee grant be used to pay fees instead of the fee payer's own balance. If an appropriate fee grant does not exist or the chain does not support fee grants, this will fail | - - - - - - - - -### ModeInfo -ModeInfo describes the signing mode of a single or nested multisig signer. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `single` | [ModeInfo.Single](#cosmos.tx.v1beta1.ModeInfo.Single) | | single represents a single signer | -| `multi` | [ModeInfo.Multi](#cosmos.tx.v1beta1.ModeInfo.Multi) | | multi represents a nested multisig signer | - - - - - - - - -### ModeInfo.Multi -Multi is the mode info for a multisig public key - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `bitarray` | [cosmos.crypto.multisig.v1beta1.CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) | | bitarray specifies which keys within the multisig are signing | -| `mode_infos` | [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) | repeated | mode_infos is the corresponding modes of the signers of the multisig which could include nested multisig public keys | - - - - - - - - -### ModeInfo.Single -Single is the mode info for a single signer. It is structured as a message -to allow for additional fields such as locale for SIGN_MODE_TEXTUAL in the -future - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `mode` | [cosmos.tx.signing.v1beta1.SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | - - - +## cosmos/auth/v1beta1/auth.proto - + -### SignDoc -SignDoc is the type used for generating sign bytes for SIGN_MODE_DIRECT. +### BaseAccount +BaseAccount defines a base account type. It contains all the necessary fields +for basic account functionality. Any custom account type should extend this +type for additional functionality (e.g. vesting). | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `body_bytes` | [bytes](#bytes) | | body_bytes is protobuf serialization of a TxBody that matches the representation in TxRaw. | -| `auth_info_bytes` | [bytes](#bytes) | | auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in TxRaw. | -| `chain_id` | [string](#string) | | chain_id is the unique identifier of the chain this transaction targets. It prevents signed transactions from being used on another chain by an attacker | -| `account_number` | [uint64](#uint64) | | account_number is the account number of the account in state | +| `address` | [string](#string) | | | +| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `account_number` | [uint64](#uint64) | | | +| `sequence` | [uint64](#uint64) | | | - + -### SignerInfo -SignerInfo describes the public key and signing mode of a single top-level -signer. +### ModuleAccount +ModuleAccount defines an account for modules that holds coins on a pool. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public_key is the public key of the signer. It is optional for accounts that already exist in state. If unset, the verifier can use the required \ signer address for this position and lookup the public key. | -| `mode_info` | [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) | | mode_info describes the signing mode of the signer and is a nested structure to support nested multisig pubkey's | -| `sequence` | [uint64](#uint64) | | sequence is the sequence of the account, which describes the number of committed transactions signed by a given address. It is used to prevent replay attacks. | +| `base_account` | [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) | | | +| `name` | [string](#string) | | | +| `permissions` | [string](#string) | repeated | | - + -### Tx -Tx is the standard type used for broadcasting transactions. +### Params +Params defines the parameters for the auth module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `body` | [TxBody](#cosmos.tx.v1beta1.TxBody) | | body is the processable content of the transaction | -| `auth_info` | [AuthInfo](#cosmos.tx.v1beta1.AuthInfo) | | auth_info is the authorization related content of the transaction, specifically signers, signer modes and fee | -| `signatures` | [bytes](#bytes) | repeated | signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to allow connecting signature meta information like public key and signing mode by position. | +| `max_memo_characters` | [uint64](#uint64) | | | +| `tx_sig_limit` | [uint64](#uint64) | | | +| `tx_size_cost_per_byte` | [uint64](#uint64) | | | +| `sig_verify_cost_ed25519` | [uint64](#uint64) | | | +| `sig_verify_cost_secp256k1` | [uint64](#uint64) | | | + - + -### TxBody -TxBody is the body of a transaction that all signers sign over. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `messages` | [google.protobuf.Any](#google.protobuf.Any) | repeated | messages is a list of messages to be executed. The required signers of those messages define the number and order of elements in AuthInfo's signer_infos and Tx's signatures. Each required signer address is added to the list only the first time it occurs. By convention, the first required signer (usually from the first message) is referred to as the primary signer and pays the fee for the whole transaction. | -| `memo` | [string](#string) | | memo is any arbitrary memo to be added to the transaction | -| `timeout_height` | [uint64](#uint64) | | timeout is the block height after which this transaction will not be processed by the chain | -| `extension_options` | [google.protobuf.Any](#google.protobuf.Any) | repeated | extension_options are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, the transaction will be rejected | -| `non_critical_extension_options` | [google.protobuf.Any](#google.protobuf.Any) | repeated | extension_options are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, they will be ignored | + +

      Top

      +## cosmos/auth/v1beta1/genesis.proto - + -### TxRaw -TxRaw is a variant of Tx that pins the signer's exact binary representation -of body and auth_info. This is used for signing, broadcasting and -verification. The binary `serialize(tx: TxRaw)` is stored in Tendermint and -the hash `sha256(serialize(tx: TxRaw))` becomes the "txhash", commonly used -as the transaction ID. +### GenesisState +GenesisState defines the auth module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `body_bytes` | [bytes](#bytes) | | body_bytes is a protobuf serialization of a TxBody that matches the representation in SignDoc. | -| `auth_info_bytes` | [bytes](#bytes) | | auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in SignDoc. | -| `signatures` | [bytes](#bytes) | repeated | signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to allow connecting signature meta information like public key and signing mode by position. | +| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines all the paramaters of the module. | +| `accounts` | [google.protobuf.Any](#google.protobuf.Any) | repeated | accounts are the accounts present at genesis. | @@ -938,266 +847,222 @@ as the transaction ID. - -

      Top

      - -## cosmos/tx/v1beta1/service.proto - - - - - -### BroadcastTxRequest -BroadcastTxRequest is the request type for the Service.BroadcastTxRequest -RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `tx_bytes` | [bytes](#bytes) | | tx_bytes is the raw transaction. | -| `mode` | [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) | | | - - + +

      Top

      +## cosmos/auth/v1beta1/query.proto - + -### BroadcastTxResponse -BroadcastTxResponse is the response type for the -Service.BroadcastTx method. +### QueryAccountRequest +QueryAccountRequest is the request type for the Query/Account RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | +| `address` | [string](#string) | | address defines the address to query for. | - + -### GetTxRequest -GetTxRequest is the request type for the Service.GetTx -RPC method. +### QueryAccountResponse +QueryAccountResponse is the response type for the Query/Account RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `hash` | [string](#string) | | hash is the tx hash to query, encoded as a hex string. | - - +| `account` | [google.protobuf.Any](#google.protobuf.Any) | | account defines the account of the corresponding address. | - -### GetTxResponse -GetTxResponse is the response type for the Service.GetTx method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the queried transaction. | -| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. - + -### GetTxsEventRequest -GetTxsEventRequest is the request type for the Service.TxsByEvents -RPC method. +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `events` | [string](#string) | repeated | events is the list of transaction event type. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - - - - +| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines the parameters of the module. | - -### GetTxsEventResponse -GetTxsEventResponse is the response type for the Service.TxsByEvents -RPC method. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `txs` | [Tx](#cosmos.tx.v1beta1.Tx) | repeated | txs is the list of queried transactions. | -| `tx_responses` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | tx_responses is the list of queried TxResponses. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | + + + + +### Query +Query defines the gRPC querier service. - +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Account` | [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) | [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) | Account returns account details based on address. | GET|/cosmos/auth/v1beta1/accounts/{address}| +| `Params` | [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) | Params queries all parameters. | GET|/cosmos/auth/v1beta1/params| -### SimulateRequest -SimulateRequest is the request type for the Service.Simulate -RPC method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the transaction to simulate. | + +

      Top

      +## cosmos/base/v1beta1/coin.proto + - +### Coin +Coin defines a token with a denomination and an amount. -### SimulateResponse -SimulateResponse is the response type for the -Service.SimulateRPC method. +NOTE: The amount field is an Int which implements the custom method +signatures required by gogoproto. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `gas_info` | [cosmos.base.abci.v1beta1.GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | gas_info is the information about gas used in the simulation. | -| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | result is the result of the simulation. | +| `denom` | [string](#string) | | | +| `amount` | [string](#string) | | | - + - +### DecCoin +DecCoin defines a token with a denomination and a decimal amount. -### BroadcastMode -BroadcastMode specifies the broadcast mode for the TxService.Broadcast RPC method. +NOTE: The amount field is an Dec which implements the custom method +signatures required by gogoproto. -| Name | Number | Description | -| ---- | ------ | ----------- | -| BROADCAST_MODE_UNSPECIFIED | 0 | zero-value for mode ordering | -| BROADCAST_MODE_BLOCK | 1 | BROADCAST_MODE_BLOCK defines a tx broadcasting mode where the client waits for the tx to be committed in a block. | -| BROADCAST_MODE_SYNC | 2 | BROADCAST_MODE_SYNC defines a tx broadcasting mode where the client waits for a CheckTx execution response only. | -| BROADCAST_MODE_ASYNC | 3 | BROADCAST_MODE_ASYNC defines a tx broadcasting mode where the client returns immediately. | +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `denom` | [string](#string) | | | +| `amount` | [string](#string) | | | - - - -### Service -Service defines a gRPC service for interacting with transactions. -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Simulate` | [SimulateRequest](#cosmos.tx.v1beta1.SimulateRequest) | [SimulateResponse](#cosmos.tx.v1beta1.SimulateResponse) | Simulate simulates executing a transaction for estimating gas usage. | POST|/cosmos/tx/v1beta1/simulate| -| `GetTx` | [GetTxRequest](#cosmos.tx.v1beta1.GetTxRequest) | [GetTxResponse](#cosmos.tx.v1beta1.GetTxResponse) | GetTx fetches a tx by hash. | GET|/cosmos/tx/v1beta1/txs/{hash}| -| `BroadcastTx` | [BroadcastTxRequest](#cosmos.tx.v1beta1.BroadcastTxRequest) | [BroadcastTxResponse](#cosmos.tx.v1beta1.BroadcastTxResponse) | BroadcastTx broadcast transaction. | POST|/cosmos/tx/v1beta1/txs| -| `GetTxsEvent` | [GetTxsEventRequest](#cosmos.tx.v1beta1.GetTxsEventRequest) | [GetTxsEventResponse](#cosmos.tx.v1beta1.GetTxsEventResponse) | GetTxsEvent fetches txs by event. | GET|/cosmos/tx/v1beta1/txs| + - +### DecProto +DecProto defines a Protobuf wrapper around a Dec object. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `dec` | [string](#string) | | | - -

      Top

      -## cosmos/tx/signing/v1beta1/signing.proto - -### SignatureDescriptor -SignatureDescriptor is a convenience type which represents the full data for -a signature including the public key of the signer, signing modes and the -signature itself. It is primarily used for coordinating signatures between -clients. + + +### IntProto +IntProto defines a Protobuf wrapper around an Int object. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public_key is the public key of the signer | -| `data` | [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) | | | -| `sequence` | [uint64](#uint64) | | sequence is the sequence of the account, which describes the number of committed transactions signed by a given address. It is used to prevent replay attacks. | +| `int` | [string](#string) | | | + - + -### SignatureDescriptor.Data -Data represents signature data + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `single` | [SignatureDescriptor.Data.Single](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Single) | | single represents a single signer | -| `multi` | [SignatureDescriptor.Data.Multi](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Multi) | | multi represents a multisig signer | + +

      Top

      +## cosmos/authz/v1beta1/authz.proto - + -### SignatureDescriptor.Data.Multi -Multi is the signature data for a multisig public key +### AuthorizationGrant +AuthorizationGrant gives permissions to execute +the provide method with expiration time. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `bitarray` | [cosmos.crypto.multisig.v1beta1.CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) | | bitarray specifies which keys within the multisig are signing | -| `signatures` | [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) | repeated | signatures is the signatures of the multi-signature | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - + -### SignatureDescriptor.Data.Single -Single is the signature data for a single signer +### GenericAuthorization +GenericAuthorization gives the grantee unrestricted permissions to execute +the provided method on behalf of the granter's account. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `mode` | [SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | -| `signature` | [bytes](#bytes) | | signature is the raw signature bytes | +| `method_name` | [string](#string) | | method name to grant unrestricted permissions to execute Note: MethodName() is already a method on `GenericAuthorization` type, we need some custom naming here so using `MessageName` | - + -### SignatureDescriptors -SignatureDescriptors wraps multiple SignatureDescriptor's. +### SendAuthorization +SendAuthorization allows the grantee to spend up to spend_limit coins from +the granter's account. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `signatures` | [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) | repeated | signatures are the signature descriptors | +| `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | @@ -1205,20 +1070,6 @@ SignatureDescriptors wraps multiple SignatureDescriptor's. - - - -### SignMode -SignMode represents a signing mode with its own security guarantees. - -| Name | Number | Description | -| ---- | ------ | ----------- | -| SIGN_MODE_UNSPECIFIED | 0 | SIGN_MODE_UNSPECIFIED specifies an unknown signing mode and will be rejected | -| SIGN_MODE_DIRECT | 1 | SIGN_MODE_DIRECT specifies a signing mode which uses SignDoc and is verified with raw bytes from Tx | -| SIGN_MODE_TEXTUAL | 2 | SIGN_MODE_TEXTUAL is a future signing mode that will verify some human-readable textual representation on top of the binary representation from SIGN_MODE_DIRECT | -| SIGN_MODE_LEGACY_AMINO_JSON | 127 | SIGN_MODE_LEGACY_AMINO_JSON is a backwards compatibility mode which uses Amino JSON and will be removed in the future | - - @@ -1227,161 +1078,188 @@ SignMode represents a signing mode with its own security guarantees. - +

      Top

      -## cosmos/crisis/v1beta1/tx.proto +## cosmos/base/abci/v1beta1/abci.proto - + -### MsgVerifyInvariant -MsgVerifyInvariant represents a message to verify a particular invariance. +### ABCIMessageLog +ABCIMessageLog defines a structure containing an indexed tx ABCI message log. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `sender` | [string](#string) | | | -| `invariant_module_name` | [string](#string) | | | -| `invariant_route` | [string](#string) | | | +| `msg_index` | [uint32](#uint32) | | | +| `log` | [string](#string) | | | +| `events` | [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) | repeated | Events contains a slice of Event objects that were emitted during some execution. | - + -### MsgVerifyInvariantResponse -MsgVerifyInvariantResponse defines the Msg/VerifyInvariant response type. +### Attribute +Attribute defines an attribute wrapper where the key and value are +strings instead of raw bytes. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [string](#string) | | | +| `value` | [string](#string) | | | - - - + - +### GasInfo +GasInfo defines tx execution gas context. -### Msg -Msg defines the bank Msg service. -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `VerifyInvariant` | [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) | [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) | VerifyInvariant defines a method to verify a particular invariance. | | +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `gas_wanted` | [uint64](#uint64) | | GasWanted is the maximum units of work we allow this tx to perform. | +| `gas_used` | [uint64](#uint64) | | GasUsed is the amount of gas actually consumed. | + + + + + + + - +### MsgData +MsgData defines the data returned in a Result object during message +execution. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `msg_type` | [string](#string) | | | +| `data` | [bytes](#bytes) | | | + - -

      Top

      -## cosmos/crisis/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the crisis module's genesis state. +### Result +Result is the union of ResponseFormat and ResponseCheckTx. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `constant_fee` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | constant_fee is the fee used to verify the invariant in the crisis module. | +| `data` | [bytes](#bytes) | | Data is any data returned from message or handler execution. It MUST be length prefixed in order to separate data from multiple message executions. | +| `log` | [string](#string) | | Log contains the log information from message or handler execution. | +| `events` | [tendermint.abci.Event](#tendermint.abci.Event) | repeated | Events contains a slice of Event objects that were emitted during message or handler execution. | - - + - +### SearchTxsResult +SearchTxsResult defines a structure for querying txs pageable - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `total_count` | [uint64](#uint64) | | Count of all txs | +| `count` | [uint64](#uint64) | | Count of txs in current page | +| `page_number` | [uint64](#uint64) | | Index of current page, start from 1 | +| `page_total` | [uint64](#uint64) | | Count of total pages | +| `limit` | [uint64](#uint64) | | Max count txs per page | +| `txs` | [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | List of txs in current page | - -

      Top

      -## cosmos/crypto/multisig/keys.proto - + -### LegacyAminoPubKey -LegacyAminoPubKey specifies a public key type -which nests multiple public keys and a threshold, -it uses legacy amino address rules. +### SimulationResponse +SimulationResponse defines the response generated when a transaction is +successfully simulated. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `threshold` | [uint32](#uint32) | | | -| `public_keys` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | +| `gas_info` | [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | | +| `result` | [Result](#cosmos.base.abci.v1beta1.Result) | | | - - + - +### StringEvent +StringEvent defines en Event object wrapper where all the attributes +contain key/value pairs that are strings instead of raw bytes. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `type` | [string](#string) | | | +| `attributes` | [Attribute](#cosmos.base.abci.v1beta1.Attribute) | repeated | | - -

      Top

      -## cosmos/crypto/multisig/v1beta1/multisig.proto - + -### CompactBitArray -CompactBitArray is an implementation of a space efficient bit array. -This is used to ensure that the encoded data takes up a minimal amount of -space after proto encoding. -This is not thread safe, and is not intended for concurrent usage. +### TxMsgData +TxMsgData defines a list of MsgData. A transaction will have a MsgData object +for each message. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `extra_bits_stored` | [uint32](#uint32) | | | -| `elems` | [bytes](#bytes) | | | +| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | | - + -### MultiSignature -MultiSignature wraps the signatures from a multisig.LegacyAminoPubKey. -See cosmos.tx.v1betata1.ModeInfo.Multi for how to specify which signers -signed and with which modes. +### TxResponse +TxResponse defines a structure containing relevant tx data and metadata. The +tags are stringified and the log is JSON decoded. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `signatures` | [bytes](#bytes) | repeated | | +| `height` | [int64](#int64) | | The block height | +| `txhash` | [string](#string) | | The transaction hash. | +| `codespace` | [string](#string) | | Namespace for the Code | +| `code` | [uint32](#uint32) | | Response code. | +| `data` | [string](#string) | | Result bytes, if any. | +| `raw_log` | [string](#string) | | The output of the application's logger (raw string). May be non-deterministic. | +| `logs` | [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) | repeated | The output of the application's logger (typed). May be non-deterministic. | +| `info` | [string](#string) | | Additional information. May be non-deterministic. | +| `gas_wanted` | [int64](#int64) | | Amount of gas requested for transaction. | +| `gas_used` | [int64](#int64) | | Amount of gas consumed by transaction. | +| `tx` | [google.protobuf.Any](#google.protobuf.Any) | | The request transaction bytes. | +| `timestamp` | [string](#string) | | Time of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time. | @@ -1397,91 +1275,97 @@ signed and with which modes. - +

      Top

      -## cosmos/crypto/secp256k1/keys.proto +## cosmos/authz/v1beta1/tx.proto - + -### PrivKey -PrivKey defines a secp256k1 private key. +### MsgExecAuthorizedRequest +MsgExecAuthorizedRequest attempts to execute the provided messages using +authorizations granted to the grantee. Each message should have only +one signer corresponding to the granter of the authorization. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | +| `grantee` | [string](#string) | | | +| `msgs` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | - + -### PubKey -PubKey defines a secp256k1 public key -Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte -if the y-coordinate is the lexicographically largest of the two associated with -the x-coordinate. Otherwise the first byte is a 0x03. -This prefix is followed with the x-coordinate. +### MsgExecAuthorizedResponse +MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse response type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | - - +| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | | - - - - + +### MsgGrantAuthorizationRequest +MsgGrantAuthorizationRequest grants the provided authorization to the grantee on the granter's +account with the provided expiration time. - -

      Top

      +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -## cosmos/crypto/ed25519/keys.proto - -### PrivKey -PrivKey defines a ed25519 private key. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | +### MsgGrantAuthorizationResponse +MsgGrantAuthorizationResponse defines the Msg/MsgGrantAuthorization response type. - + -### PubKey -PubKey defines a ed25519 public key -Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte -if the y-coordinate is the lexicographically largest of the two associated with -the x-coordinate. Otherwise the first byte is a 0x03. -This prefix is followed with the x-coordinate. +### MsgRevokeAuthorizationRequest +MsgRevokeAuthorizationRequest revokes any authorization with the provided sdk.Msg type on the +granter's account with that has been granted to the grantee. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `method_name` | [string](#string) | | | + + + + + + + + +### MsgRevokeAuthorizationResponse +MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse response type. @@ -1493,89 +1377,118 @@ This prefix is followed with the x-coordinate. + + + +### Msg +Msg defines the authz Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `GrantAuthorization` | [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) | [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) | GrantAuthorization grants the provided authorization to the grantee on the granter's account with the provided expiration time. | | +| `ExecAuthorized` | [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) | [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) | ExecAuthorized attempts to execute the provided messages using authorizations granted to the grantee. Each message should have only one signer corresponding to the granter of the authorization. | | +| `RevokeAuthorization` | [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) | [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) | RevokeAuthorization revokes any authorization corresponding to the provided method name on the granter's account that has been granted to the grantee. | | + - +

      Top

      -## cosmos/mint/v1beta1/query.proto - +## cosmos/authz/v1beta1/genesis.proto - -### QueryAnnualProvisionsRequest -QueryAnnualProvisionsRequest is the request type for the -Query/AnnualProvisions RPC method. + +### GenesisState +GenesisState defines the authz module's genesis state. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `authorization` | [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) | repeated | | - -### QueryAnnualProvisionsResponse -QueryAnnualProvisionsResponse is the response type for the -Query/AnnualProvisions RPC method. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `annual_provisions` | [bytes](#bytes) | | annual_provisions is the current minting annual provisions value. | + +### GrantAuthorization +GrantAuthorization defines the GenesisState/GrantAuthorization type. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - -### QueryInflationRequest -QueryInflationRequest is the request type for the Query/Inflation RPC method. + + + + - -### QueryInflationResponse -QueryInflationResponse is the response type for the Query/Inflation RPC -method. + +

      Top

      +## cosmos/base/query/v1beta1/pagination.proto -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `inflation` | [bytes](#bytes) | | inflation is the current minting inflation value. | + +### PageRequest +PageRequest is to be embedded in gRPC request messages for efficient +pagination. Ex: + message SomeRequest { + Foo some_parameter = 1; + PageRequest pagination = 2; + } - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | key is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be set. | +| `offset` | [uint64](#uint64) | | offset is a numeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be set. | +| `limit` | [uint64](#uint64) | | limit is the total number of results to be returned in the result page. If left empty it will default to a value to be set by each app. | +| `count_total` | [bool](#bool) | | count_total is set to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. count_total is only respected when offset is used. It is ignored when key is set. | -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. + - +### PageResponse +PageResponse is to be embedded in gRPC response messages where the +corresponding request message has used PageRequest. -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method. + message SomeResponse { + repeated Bar results = 1; + PageResponse page = 2; + } | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines the parameters of the module. | +| `next_key` | [bytes](#bytes) | | next_key is the key to be passed to PageRequest.key to query the next page most efficiently | +| `total` | [uint64](#uint64) | | total is total number of results available if PageRequest.count_total was set, its value is undefined otherwise | @@ -1587,91 +1500,76 @@ QueryParamsResponse is the response type for the Query/Params RPC method. - - - -### Query -Query provides defines the gRPC querier service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Params` | [QueryParamsRequest](#cosmos.mint.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.mint.v1beta1.QueryParamsResponse) | Params returns the total set of minting parameters. | GET|/cosmos/mint/v1beta1/params| -| `Inflation` | [QueryInflationRequest](#cosmos.mint.v1beta1.QueryInflationRequest) | [QueryInflationResponse](#cosmos.mint.v1beta1.QueryInflationResponse) | Inflation returns the current minting inflation value. | GET|/cosmos/mint/v1beta1/inflation| -| `AnnualProvisions` | [QueryAnnualProvisionsRequest](#cosmos.mint.v1beta1.QueryAnnualProvisionsRequest) | [QueryAnnualProvisionsResponse](#cosmos.mint.v1beta1.QueryAnnualProvisionsResponse) | AnnualProvisions current minting annual provisions value. | GET|/cosmos/mint/v1beta1/annual_provisions| - - +

      Top

      -## cosmos/mint/v1beta1/genesis.proto +## cosmos/authz/v1beta1/query.proto - + -### GenesisState -GenesisState defines the mint module's genesis state. +### QueryAuthorizationRequest +QueryAuthorizationRequest is the request type for the Query/Authorization RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `minter` | [Minter](#cosmos.mint.v1beta1.Minter) | | minter is a space for holding current inflation information. | -| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines all the paramaters of the module. | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `method_name` | [string](#string) | | | - - + - +### QueryAuthorizationResponse +QueryAuthorizationResponse is the response type for the Query/Authorization RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `authorization` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | | authorization is a authorization granted for grantee by granter. | - -

      Top

      -## cosmos/mint/v1beta1/mint.proto - + -### Minter -Minter represents the minting state. +### QueryAuthorizationsRequest +QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `inflation` | [string](#string) | | current annual inflation rate | -| `annual_provisions` | [string](#string) | | current annual expected provisions | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - + -### Params -Params holds parameters for the mint module. +### QueryAuthorizationsResponse +QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `mint_denom` | [string](#string) | | type of coin to mint | -| `inflation_rate_change` | [string](#string) | | maximum annual change in inflation rate | -| `inflation_max` | [string](#string) | | maximum inflation rate | -| `inflation_min` | [string](#string) | | minimum inflation rate | -| `goal_bonded` | [string](#string) | | goal of percent bonded atoms | -| `blocks_per_year` | [uint64](#uint64) | | expected blocks per year | +| `authorizations` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | repeated | authorizations is a list of grants granted for grantee by granter. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | @@ -1683,178 +1581,191 @@ Params holds parameters for the mint module. + + + +### Query +Query defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Authorization` | [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) | [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) | Returns any `Authorization` (or `nil`), with the expiration time, granted to the grantee by the granter for the provided msg type. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grant| +| `Authorizations` | [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) | [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) | Returns list of `Authorization`, granted to the grantee by the granter. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grants| + - +

      Top

      -## cosmos/feegrant/v1beta1/feegrant.proto +## cosmos/bank/v1beta1/bank.proto - + -### BasicFeeAllowance -BasicFeeAllowance implements FeeAllowance with a one-time grant of tokens -that optionally expires. The delegatee can use up to SpendLimit to cover fees. +### DenomUnit +DenomUnit represents a struct that describes a given +denomination unit of the basic token. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `expiration` | [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) | | | +| `denom` | [string](#string) | | denom represents the string name of the given denom unit (e.g uatom). | +| `exponent` | [uint32](#uint32) | | exponent represents power of 10 exponent that one must raise the base_denom to in order to equal the given DenomUnit's denom 1 denom = 1^exponent base_denom (e.g. with a base_denom of uatom, one can create a DenomUnit of 'atom' with exponent = 6, thus: 1 atom = 10^6 uatom). | +| `aliases` | [string](#string) | repeated | aliases is a list of string aliases for the given denom | - + -### Duration -Duration is a span of a clock time or number of blocks. -This is designed to be added to an ExpiresAt struct. +### Input +Input models transaction input. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `duration` | [google.protobuf.Duration](#google.protobuf.Duration) | | | -| `blocks` | [uint64](#uint64) | | | +| `address` | [string](#string) | | | +| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - + -### ExpiresAt -ExpiresAt is a point in time where something expires. -It may be *either* block time or block height +### Metadata +Metadata represents a struct that describes +a basic token. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `height` | [int64](#int64) | | | +| `description` | [string](#string) | | | +| `denom_units` | [DenomUnit](#cosmos.bank.v1beta1.DenomUnit) | repeated | denom_units represents the list of DenomUnit's for a given coin | +| `base` | [string](#string) | | base represents the base denom (should be the DenomUnit with exponent = 0). | +| `display` | [string](#string) | | display indicates the suggested denom that should be displayed in clients. | - + -### FeeAllowanceGrant -FeeAllowanceGrant is stored in the KVStore to record a grant with full context +### Output +Output models transaction outputs. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `address` | [string](#string) | | | +| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - + -### PeriodicFeeAllowance -PeriodicFeeAllowance extends FeeAllowance to allow for both a maximum cap, -as well as a limit per time period. +### Params +Params defines the parameters for the bank module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `basic` | [BasicFeeAllowance](#cosmos.feegrant.v1beta1.BasicFeeAllowance) | | | -| `period` | [Duration](#cosmos.feegrant.v1beta1.Duration) | | | -| `period_spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `period_can_spend` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `period_reset` | [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) | | | +| `send_enabled` | [SendEnabled](#cosmos.bank.v1beta1.SendEnabled) | repeated | | +| `default_send_enabled` | [bool](#bool) | | | - - + - +### SendEnabled +SendEnabled maps coin denom to a send_enabled status (whether a denom is +sendable). - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `denom` | [string](#string) | | | +| `enabled` | [bool](#bool) | | | - -

      Top

      -## cosmos/feegrant/v1beta1/query.proto - + -### QueryFeeAllowanceRequest -QueryFeeAllowanceRequest is the request type for the Query/FeeAllowance RPC method. +### Supply +Supply represents a struct that passively keeps track of the total supply +amounts in the network. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | +| `total` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | + - + -### QueryFeeAllowanceResponse -QueryFeeAllowanceResponse is the response type for the Query/FeeAllowance RPC method. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `fee_allowance` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | | fee_allowance is a fee_allowance granted for grantee by granter. | + +

      Top

      +## cosmos/bank/v1beta1/genesis.proto - + -### QueryFeeAllowancesRequest -QueryFeeAllowancesRequest is the request type for the Query/FeeAllowances RPC method. +### Balance +Balance defines an account address and balance pair used in the bank module's +genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `grantee` | [string](#string) | | | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | +| `address` | [string](#string) | | address is the address of the balance holder. | +| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | coins defines the different coins this balance holds. | - + -### QueryFeeAllowancesResponse -QueryFeeAllowancesResponse is the response type for the Query/FeeAllowances RPC method. +### GenesisState +GenesisState defines the bank module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `fee_allowances` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | repeated | fee_allowances are fee_allowance's granted for grantee by granter. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | +| `params` | [Params](#cosmos.bank.v1beta1.Params) | | params defines all the paramaters of the module. | +| `balances` | [Balance](#cosmos.bank.v1beta1.Balance) | repeated | balances is an array containing the balances of all the accounts. | +| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply represents the total supply. | +| `denom_metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | denom_metadata defines the metadata of the differents coins. | @@ -1866,231 +1777,220 @@ QueryFeeAllowancesResponse is the response type for the Query/FeeAllowances RPC + - -### Query -Query defines the gRPC querier service. -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `FeeAllowance` | [QueryFeeAllowanceRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowanceRequest) | [QueryFeeAllowanceResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowanceResponse) | FeeAllowance returns fee granted to the grantee by the granter. | GET|/cosmos/feegrant/v1beta1/fee_allowance/{granter}/{grantee}| -| `FeeAllowances` | [QueryFeeAllowancesRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowancesRequest) | [QueryFeeAllowancesResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowancesResponse) | FeeAllowances returns all the grants for address. | GET|/cosmos/feegrant/v1beta1/fee_allowances/{grantee}| + +

      Top

      - +## cosmos/bank/v1beta1/query.proto - -

      Top

      + -## cosmos/feegrant/v1beta1/tx.proto +### QueryAllBalancesRequest +QueryBalanceRequest is the request type for the Query/AllBalances RPC method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | address is the address to query balances for. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - -### MsgGrantFeeAllowance -MsgGrantFeeAllowance adds permission for Grantee to spend up to Allowance -of fees from the account of Granter. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | + + + + +### QueryAllBalancesResponse +QueryAllBalancesResponse is the response type for the Query/AllBalances RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `balances` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | balances is the balances of all the coins. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | + + + +### QueryBalanceRequest +QueryBalanceRequest is the request type for the Query/Balance RPC method. - -### MsgGrantFeeAllowanceResponse -MsgGrantFeeAllowanceResponse defines the Msg/GrantFeeAllowanceResponse response type. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | address is the address to query balances for. | +| `denom` | [string](#string) | | denom is the coin denom to query balances for. | - + -### MsgRevokeFeeAllowance -MsgRevokeFeeAllowance removes any existing FeeAllowance from Granter to Grantee. +### QueryBalanceResponse +QueryBalanceResponse is the response type for the Query/Balance RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | - - +| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | balance is the balance of the coin. | - -### MsgRevokeFeeAllowanceResponse -MsgRevokeFeeAllowanceResponse defines the Msg/RevokeFeeAllowanceResponse response type. + +### QueryDenomMetadataRequest +QueryDenomMetadataRequest is the request type for the Query/DenomMetadata RPC method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `denom` | [string](#string) | | denom is the coin denom to query the metadata for. | - - - - -### Msg -Msg defines the feegrant msg service. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `GrantFeeAllowance` | [MsgGrantFeeAllowance](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowance) | [MsgGrantFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowanceResponse) | GrantFeeAllowance grants fee allowance to the grantee on the granter's account with the provided expiration time. | | -| `RevokeFeeAllowance` | [MsgRevokeFeeAllowance](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowance) | [MsgRevokeFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowanceResponse) | RevokeFeeAllowance revokes any fee allowance of granter's account that has been granted to the grantee. | | +### QueryDenomMetadataResponse +QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC +method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | | metadata describes and provides all the client information for the requested token. | - -

      Top

      -## cosmos/feegrant/v1beta1/genesis.proto - + -### GenesisState -GenesisState contains a set of fee allowances, persisted from the store +### QueryDenomsMetadataRequest +QueryDenomsMetadataRequest is the request type for the Query/DenomsMetadata RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `fee_allowances` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | repeated | | - - +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - - - - + +### QueryDenomsMetadataResponse +QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata RPC +method. - -

      Top

      +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `metadatas` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | metadata provides the client information for all the registered tokens. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | -## cosmos/capability/v1beta1/capability.proto - -### Capability -Capability defines an implementation of an object capability. The index -provided to a Capability must be globally unique. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `index` | [uint64](#uint64) | | | +### QueryParamsRequest +QueryParamsRequest defines the request type for querying x/bank parameters. - + -### CapabilityOwners -CapabilityOwners defines a set of owners of a single Capability. The set of -owners must be unique. +### QueryParamsResponse +QueryParamsResponse defines the response type for querying x/bank parameters. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `owners` | [Owner](#cosmos.capability.v1beta1.Owner) | repeated | | +| `params` | [Params](#cosmos.bank.v1beta1.Params) | | | - + -### Owner -Owner defines a single capability owner. An owner is defined by the name of -capability and the module name. +### QuerySupplyOfRequest +QuerySupplyOfRequest is the request type for the Query/SupplyOf RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `module` | [string](#string) | | | -| `name` | [string](#string) | | | - - +| `denom` | [string](#string) | | denom is the coin denom to query balances for. | - - - - + +### QuerySupplyOfResponse +QuerySupplyOfResponse is the response type for the Query/SupplyOf RPC method. - -

      Top

      +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | amount is the supply of the coin. | -## cosmos/capability/v1beta1/genesis.proto - -### GenesisOwners -GenesisOwners defines the capability owners with their corresponding index. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `index` | [uint64](#uint64) | | index is the index of the capability owner. | -| `index_owners` | [CapabilityOwners](#cosmos.capability.v1beta1.CapabilityOwners) | | index_owners are the owners at the given index. | +### QueryTotalSupplyRequest +QueryTotalSupplyRequest is the request type for the Query/TotalSupply RPC +method. - + -### GenesisState -GenesisState defines the capability module's genesis state. +### QueryTotalSupplyResponse +QueryTotalSupplyResponse is the response type for the Query/TotalSupply RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `index` | [uint64](#uint64) | | index is the capability global index. | -| `owners` | [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) | repeated | owners represents a map from index to owners of the capability index index key is string to allow amino marshalling. | +| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply is the supply of the coins | @@ -2102,129 +2002,138 @@ GenesisState defines the capability module's genesis state. + + + +### Query +Query defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Balance` | [QueryBalanceRequest](#cosmos.bank.v1beta1.QueryBalanceRequest) | [QueryBalanceResponse](#cosmos.bank.v1beta1.QueryBalanceResponse) | Balance queries the balance of a single coin for a single account. | GET|/cosmos/bank/v1beta1/balances/{address}/{denom}| +| `AllBalances` | [QueryAllBalancesRequest](#cosmos.bank.v1beta1.QueryAllBalancesRequest) | [QueryAllBalancesResponse](#cosmos.bank.v1beta1.QueryAllBalancesResponse) | AllBalances queries the balance of all coins for a single account. | GET|/cosmos/bank/v1beta1/balances/{address}| +| `TotalSupply` | [QueryTotalSupplyRequest](#cosmos.bank.v1beta1.QueryTotalSupplyRequest) | [QueryTotalSupplyResponse](#cosmos.bank.v1beta1.QueryTotalSupplyResponse) | TotalSupply queries the total supply of all coins. | GET|/cosmos/bank/v1beta1/supply| +| `SupplyOf` | [QuerySupplyOfRequest](#cosmos.bank.v1beta1.QuerySupplyOfRequest) | [QuerySupplyOfResponse](#cosmos.bank.v1beta1.QuerySupplyOfResponse) | SupplyOf queries the supply of a single coin. | GET|/cosmos/bank/v1beta1/supply/{denom}| +| `Params` | [QueryParamsRequest](#cosmos.bank.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.bank.v1beta1.QueryParamsResponse) | Params queries the parameters of x/bank module. | GET|/cosmos/bank/v1beta1/params| +| `DenomMetadata` | [QueryDenomMetadataRequest](#cosmos.bank.v1beta1.QueryDenomMetadataRequest) | [QueryDenomMetadataResponse](#cosmos.bank.v1beta1.QueryDenomMetadataResponse) | DenomsMetadata queries the client metadata of a given coin denomination. | GET|/cosmos/bank/v1beta1/denoms_metadata/{denom}| +| `DenomsMetadata` | [QueryDenomsMetadataRequest](#cosmos.bank.v1beta1.QueryDenomsMetadataRequest) | [QueryDenomsMetadataResponse](#cosmos.bank.v1beta1.QueryDenomsMetadataResponse) | DenomsMetadata queries the client metadata for all registered coin denominations. | GET|/cosmos/bank/v1beta1/denoms_metadata| + - +

      Top

      -## cosmos/bank/v1beta1/bank.proto +## cosmos/bank/v1beta1/tx.proto - + -### DenomUnit -DenomUnit represents a struct that describes a given -denomination unit of the basic token. +### MsgMultiSend +MsgMultiSend represents an arbitrary multi-in, multi-out send message. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | denom represents the string name of the given denom unit (e.g uatom). | -| `exponent` | [uint32](#uint32) | | exponent represents power of 10 exponent that one must raise the base_denom to in order to equal the given DenomUnit's denom 1 denom = 1^exponent base_denom (e.g. with a base_denom of uatom, one can create a DenomUnit of 'atom' with exponent = 6, thus: 1 atom = 10^6 uatom). | -| `aliases` | [string](#string) | repeated | aliases is a list of string aliases for the given denom | - - +| `inputs` | [Input](#cosmos.bank.v1beta1.Input) | repeated | | +| `outputs` | [Output](#cosmos.bank.v1beta1.Output) | repeated | | - -### Input -Input models transaction input. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +### MsgMultiSendResponse +MsgMultiSendResponse defines the Msg/MultiSend response type. - + -### Metadata -Metadata represents a struct that describes -a basic token. +### MsgSend +MsgSend represents a message to send coins from one account to another. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `description` | [string](#string) | | | -| `denom_units` | [DenomUnit](#cosmos.bank.v1beta1.DenomUnit) | repeated | denom_units represents the list of DenomUnit's for a given coin | -| `base` | [string](#string) | | base represents the base denom (should be the DenomUnit with exponent = 0). | -| `display` | [string](#string) | | display indicates the suggested denom that should be displayed in clients. | +| `from_address` | [string](#string) | | | +| `to_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - + + +### MsgSendResponse +MsgSendResponse defines the Msg/Send response type. -### Output -Output models transaction outputs. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | + + + - + -### Params -Params defines the parameters for the bank module. +### Msg +Msg defines the bank Msg service. +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Send` | [MsgSend](#cosmos.bank.v1beta1.MsgSend) | [MsgSendResponse](#cosmos.bank.v1beta1.MsgSendResponse) | Send defines a method for sending coins from one account to another account. | | +| `MultiSend` | [MsgMultiSend](#cosmos.bank.v1beta1.MsgMultiSend) | [MsgMultiSendResponse](#cosmos.bank.v1beta1.MsgMultiSendResponse) | MultiSend defines a method for sending coins from some accounts to other accounts. | | -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `send_enabled` | [SendEnabled](#cosmos.bank.v1beta1.SendEnabled) | repeated | | -| `default_send_enabled` | [bool](#bool) | | | + + +

      Top

      +## cosmos/base/kv/v1beta1/kv.proto - -### SendEnabled -SendEnabled maps coin denom to a send_enabled status (whether a denom is -sendable). + + +### Pair +Pair defines a key/value bytes tuple. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | | -| `enabled` | [bool](#bool) | | | +| `key` | [bytes](#bytes) | | | +| `value` | [bytes](#bytes) | | | - + -### Supply -Supply represents a struct that passively keeps track of the total supply -amounts in the network. +### Pairs +Pairs defines a repeated slice of Pair objects. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `total` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `pairs` | [Pair](#cosmos.base.kv.v1beta1.Pair) | repeated | | @@ -2240,509 +2149,502 @@ amounts in the network. - +

      Top

      -## cosmos/bank/v1beta1/query.proto - - +## cosmos/base/reflection/v1beta1/reflection.proto - -### QueryAllBalancesRequest -QueryBalanceRequest is the request type for the Query/AllBalances RPC method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the address to query balances for. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +### ListAllInterfacesRequest +ListAllInterfacesRequest is the request type of the ListAllInterfaces RPC. - + -### QueryAllBalancesResponse -QueryAllBalancesResponse is the response type for the Query/AllBalances RPC -method. +### ListAllInterfacesResponse +ListAllInterfacesResponse is the response type of the ListAllInterfaces RPC. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `balances` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | balances is the balances of all the coins. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| `interface_names` | [string](#string) | repeated | interface_names is an array of all the registered interfaces. | - + -### QueryBalanceRequest -QueryBalanceRequest is the request type for the Query/Balance RPC method. +### ListImplementationsRequest +ListImplementationsRequest is the request type of the ListImplementations +RPC. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the address to query balances for. | -| `denom` | [string](#string) | | denom is the coin denom to query balances for. | +| `interface_name` | [string](#string) | | interface_name defines the interface to query the implementations for. | - + -### QueryBalanceResponse -QueryBalanceResponse is the response type for the Query/Balance RPC method. +### ListImplementationsResponse +ListImplementationsResponse is the response type of the ListImplementations +RPC. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | balance is the balance of the coin. | - - - - - +| `implementation_message_names` | [string](#string) | repeated | | - -### QueryDenomMetadataRequest -QueryDenomMetadataRequest is the request type for the Query/DenomMetadata RPC method. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | denom is the coin denom to query the metadata for. | + + + + - +### ReflectionService +ReflectionService defines a service for interface reflection. -### QueryDenomMetadataResponse -QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC -method. +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `ListAllInterfaces` | [ListAllInterfacesRequest](#cosmos.base.reflection.v1beta1.ListAllInterfacesRequest) | [ListAllInterfacesResponse](#cosmos.base.reflection.v1beta1.ListAllInterfacesResponse) | ListAllInterfaces lists all the interfaces registered in the interface registry. | GET|/cosmos/base/reflection/v1beta1/interfaces| +| `ListImplementations` | [ListImplementationsRequest](#cosmos.base.reflection.v1beta1.ListImplementationsRequest) | [ListImplementationsResponse](#cosmos.base.reflection.v1beta1.ListImplementationsResponse) | ListImplementations list all the concrete types that implement a given interface. | GET|/cosmos/base/reflection/v1beta1/interfaces/{interface_name}/implementations| + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | | metadata describes and provides all the client information for the requested token. | + +

      Top

      +## cosmos/base/snapshots/v1beta1/snapshot.proto - + -### QueryDenomsMetadataRequest -QueryDenomsMetadataRequest is the request type for the Query/DenomsMetadata RPC method. +### Metadata +Metadata contains SDK-specific snapshot metadata. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +| `chunk_hashes` | [bytes](#bytes) | repeated | SHA-256 chunk hashes | - + -### QueryDenomsMetadataResponse -QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata RPC -method. +### Snapshot +Snapshot contains Tendermint state sync snapshot info. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `metadatas` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | metadata provides the client information for all the registered tokens. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| `height` | [uint64](#uint64) | | | +| `format` | [uint32](#uint32) | | | +| `chunks` | [uint32](#uint32) | | | +| `hash` | [bytes](#bytes) | | | +| `metadata` | [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) | | | + - + -### QueryParamsRequest -QueryParamsRequest defines the request type for querying x/bank parameters. + + + +

      Top

      +## cosmos/base/store/v1beta1/commit_info.proto - -### QueryParamsResponse -QueryParamsResponse defines the response type for querying x/bank parameters. + + + +### CommitID +CommitID defines the committment information when a specific store is +committed. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.bank.v1beta1.Params) | | | +| `version` | [int64](#int64) | | | +| `hash` | [bytes](#bytes) | | | - + -### QuerySupplyOfRequest -QuerySupplyOfRequest is the request type for the Query/SupplyOf RPC method. +### CommitInfo +CommitInfo defines commit information used by the multi-store when committing +a version/height. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | denom is the coin denom to query balances for. | +| `version` | [int64](#int64) | | | +| `store_infos` | [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) | repeated | | - + -### QuerySupplyOfResponse -QuerySupplyOfResponse is the response type for the Query/SupplyOf RPC method. +### StoreInfo +StoreInfo defines store-specific commit information. It contains a reference +between a store name and the commit ID. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | amount is the supply of the coin. | - - +| `name` | [string](#string) | | | +| `commit_id` | [CommitID](#cosmos.base.store.v1beta1.CommitID) | | | - -### QueryTotalSupplyRequest -QueryTotalSupplyRequest is the request type for the Query/TotalSupply RPC -method. + + + + - + +

      Top

      -### QueryTotalSupplyResponse -QueryTotalSupplyResponse is the response type for the Query/TotalSupply RPC -method +## cosmos/base/store/v1beta1/snapshot.proto -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply is the supply of the coins | + +### SnapshotIAVLItem +SnapshotIAVLItem is an exported IAVL node. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | | +| `value` | [bytes](#bytes) | | | +| `version` | [int64](#int64) | | | +| `height` | [int32](#int32) | | | - - - - -### Query -Query defines the gRPC querier service. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Balance` | [QueryBalanceRequest](#cosmos.bank.v1beta1.QueryBalanceRequest) | [QueryBalanceResponse](#cosmos.bank.v1beta1.QueryBalanceResponse) | Balance queries the balance of a single coin for a single account. | GET|/cosmos/bank/v1beta1/balances/{address}/{denom}| -| `AllBalances` | [QueryAllBalancesRequest](#cosmos.bank.v1beta1.QueryAllBalancesRequest) | [QueryAllBalancesResponse](#cosmos.bank.v1beta1.QueryAllBalancesResponse) | AllBalances queries the balance of all coins for a single account. | GET|/cosmos/bank/v1beta1/balances/{address}| -| `TotalSupply` | [QueryTotalSupplyRequest](#cosmos.bank.v1beta1.QueryTotalSupplyRequest) | [QueryTotalSupplyResponse](#cosmos.bank.v1beta1.QueryTotalSupplyResponse) | TotalSupply queries the total supply of all coins. | GET|/cosmos/bank/v1beta1/supply| -| `SupplyOf` | [QuerySupplyOfRequest](#cosmos.bank.v1beta1.QuerySupplyOfRequest) | [QuerySupplyOfResponse](#cosmos.bank.v1beta1.QuerySupplyOfResponse) | SupplyOf queries the supply of a single coin. | GET|/cosmos/bank/v1beta1/supply/{denom}| -| `Params` | [QueryParamsRequest](#cosmos.bank.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.bank.v1beta1.QueryParamsResponse) | Params queries the parameters of x/bank module. | GET|/cosmos/bank/v1beta1/params| -| `DenomMetadata` | [QueryDenomMetadataRequest](#cosmos.bank.v1beta1.QueryDenomMetadataRequest) | [QueryDenomMetadataResponse](#cosmos.bank.v1beta1.QueryDenomMetadataResponse) | DenomsMetadata queries the client metadata of a given coin denomination. | GET|/cosmos/bank/v1beta1/denoms_metadata/{denom}| -| `DenomsMetadata` | [QueryDenomsMetadataRequest](#cosmos.bank.v1beta1.QueryDenomsMetadataRequest) | [QueryDenomsMetadataResponse](#cosmos.bank.v1beta1.QueryDenomsMetadataResponse) | DenomsMetadata queries the client metadata for all registered coin denominations. | GET|/cosmos/bank/v1beta1/denoms_metadata| +### SnapshotItem +SnapshotItem is an item contained in a rootmulti.Store snapshot. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `store` | [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) | | | +| `iavl` | [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) | | | - -

      Top

      -## cosmos/bank/v1beta1/tx.proto - + -### MsgMultiSend -MsgMultiSend represents an arbitrary multi-in, multi-out send message. +### SnapshotStoreItem +SnapshotStoreItem contains metadata about a snapshotted store. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `inputs` | [Input](#cosmos.bank.v1beta1.Input) | repeated | | -| `outputs` | [Output](#cosmos.bank.v1beta1.Output) | repeated | | +| `name` | [string](#string) | | | + + + - + + + -### MsgMultiSendResponse -MsgMultiSendResponse defines the Msg/MultiSend response type. + +

      Top

      +## cosmos/base/tendermint/v1beta1/query.proto - + -### MsgSend -MsgSend represents a message to send coins from one account to another. +### GetBlockByHeightRequest +GetBlockByHeightRequest is the request type for the Query/GetBlockByHeight RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `from_address` | [string](#string) | | | -| `to_address` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `height` | [int64](#int64) | | | - + -### MsgSendResponse -MsgSendResponse defines the Msg/Send response type. +### GetBlockByHeightResponse +GetBlockByHeightResponse is the response type for the Query/GetBlockByHeight RPC method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | +| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | - - - + - +### GetLatestBlockRequest +GetLatestBlockRequest is the request type for the Query/GetLatestBlock RPC method. -### Msg -Msg defines the bank Msg service. -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Send` | [MsgSend](#cosmos.bank.v1beta1.MsgSend) | [MsgSendResponse](#cosmos.bank.v1beta1.MsgSendResponse) | Send defines a method for sending coins from one account to another account. | | -| `MultiSend` | [MsgMultiSend](#cosmos.bank.v1beta1.MsgMultiSend) | [MsgMultiSendResponse](#cosmos.bank.v1beta1.MsgMultiSendResponse) | MultiSend defines a method for sending coins from some accounts to other accounts. | | - - -

      Top

      + + +### GetLatestBlockResponse +GetLatestBlockResponse is the response type for the Query/GetLatestBlock RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | +| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | + -## cosmos/bank/v1beta1/genesis.proto - -### Balance -Balance defines an account address and balance pair used in the bank module's -genesis state. + + +### GetLatestValidatorSetRequest +GetLatestValidatorSetRequest is the request type for the Query/GetValidatorSetByHeight RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the address of the balance holder. | -| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | coins defines the different coins this balance holds. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - + -### GenesisState -GenesisState defines the bank module's genesis state. +### GetLatestValidatorSetResponse +GetLatestValidatorSetResponse is the response type for the Query/GetValidatorSetByHeight RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.bank.v1beta1.Params) | | params defines all the paramaters of the module. | -| `balances` | [Balance](#cosmos.bank.v1beta1.Balance) | repeated | balances is an array containing the balances of all the accounts. | -| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply represents the total supply. | -| `denom_metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | denom_metadata defines the metadata of the differents coins. | - - +| `block_height` | [int64](#int64) | | | +| `validators` | [Validator](#cosmos.base.tendermint.v1beta1.Validator) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | - - - - + +### GetNodeInfoRequest +GetNodeInfoRequest is the request type for the Query/GetNodeInfo RPC method. - -

      Top

      -## cosmos/authz/v1beta1/authz.proto - + -### AuthorizationGrant -AuthorizationGrant gives permissions to execute -the provide method with expiration time. +### GetNodeInfoResponse +GetNodeInfoResponse is the request type for the Query/GetNodeInfo RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - - +| `default_node_info` | [tendermint.p2p.DefaultNodeInfo](#tendermint.p2p.DefaultNodeInfo) | | | +| `application_version` | [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) | | | - -### GenericAuthorization -GenericAuthorization gives the grantee unrestricted permissions to execute -the provided method on behalf of the granter's account. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `method_name` | [string](#string) | | method name to grant unrestricted permissions to execute Note: MethodName() is already a method on `GenericAuthorization` type, we need some custom naming here so using `MessageName` | +### GetSyncingRequest +GetSyncingRequest is the request type for the Query/GetSyncing RPC method. - + -### SendAuthorization -SendAuthorization allows the grantee to spend up to spend_limit coins from -the granter's account. +### GetSyncingResponse +GetSyncingResponse is the response type for the Query/GetSyncing RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `syncing` | [bool](#bool) | | | - - + - +### GetValidatorSetByHeightRequest +GetValidatorSetByHeightRequest is the request type for the Query/GetValidatorSetByHeight RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [int64](#int64) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - -

      Top

      -## cosmos/authz/v1beta1/query.proto - + -### QueryAuthorizationRequest -QueryAuthorizationRequest is the request type for the Query/Authorization RPC method. +### GetValidatorSetByHeightResponse +GetValidatorSetByHeightResponse is the response type for the Query/GetValidatorSetByHeight RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `method_name` | [string](#string) | | | +| `block_height` | [int64](#int64) | | | +| `validators` | [Validator](#cosmos.base.tendermint.v1beta1.Validator) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | - + -### QueryAuthorizationResponse -QueryAuthorizationResponse is the response type for the Query/Authorization RPC method. +### Module +Module is the type for VersionInfo | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorization` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | | authorization is a authorization granted for grantee by granter. | +| `path` | [string](#string) | | module path | +| `version` | [string](#string) | | module version | +| `sum` | [string](#string) | | checksum | - + -### QueryAuthorizationsRequest -QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. +### Validator +Validator is the type for the validator-set. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | +| `address` | [string](#string) | | | +| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `voting_power` | [int64](#int64) | | | +| `proposer_priority` | [int64](#int64) | | | - + -### QueryAuthorizationsResponse -QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. +### VersionInfo +VersionInfo is the type for the GetNodeInfoResponse message. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorizations` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | repeated | authorizations is a list of grants granted for grantee by granter. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | +| `name` | [string](#string) | | | +| `app_name` | [string](#string) | | | +| `version` | [string](#string) | | | +| `git_commit` | [string](#string) | | | +| `build_tags` | [string](#string) | | | +| `go_version` | [string](#string) | | | +| `build_deps` | [Module](#cosmos.base.tendermint.v1beta1.Module) | repeated | | @@ -2755,111 +2657,74 @@ QueryAuthorizationsResponse is the response type for the Query/Authorizations RP - + -### Query -Query defines the gRPC querier service. +### Service +Service defines the gRPC querier service for tendermint queries. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Authorization` | [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) | [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) | Returns any `Authorization` (or `nil`), with the expiration time, granted to the grantee by the granter for the provided msg type. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grant| -| `Authorizations` | [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) | [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) | Returns list of `Authorization`, granted to the grantee by the granter. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grants| +| `GetNodeInfo` | [GetNodeInfoRequest](#cosmos.base.tendermint.v1beta1.GetNodeInfoRequest) | [GetNodeInfoResponse](#cosmos.base.tendermint.v1beta1.GetNodeInfoResponse) | GetNodeInfo queries the current node info. | GET|/cosmos/base/tendermint/v1beta1/node_info| +| `GetSyncing` | [GetSyncingRequest](#cosmos.base.tendermint.v1beta1.GetSyncingRequest) | [GetSyncingResponse](#cosmos.base.tendermint.v1beta1.GetSyncingResponse) | GetSyncing queries node syncing. | GET|/cosmos/base/tendermint/v1beta1/syncing| +| `GetLatestBlock` | [GetLatestBlockRequest](#cosmos.base.tendermint.v1beta1.GetLatestBlockRequest) | [GetLatestBlockResponse](#cosmos.base.tendermint.v1beta1.GetLatestBlockResponse) | GetLatestBlock returns the latest block. | GET|/cosmos/base/tendermint/v1beta1/blocks/latest| +| `GetBlockByHeight` | [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) | [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) | GetBlockByHeight queries block for given height. | GET|/cosmos/base/tendermint/v1beta1/blocks/{height}| +| `GetLatestValidatorSet` | [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) | [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) | GetLatestValidatorSet queries latest validator-set. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/latest| +| `GetValidatorSetByHeight` | [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) | [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) | GetValidatorSetByHeight queries validator-set at a given height. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/{height}| - +

      Top

      -## cosmos/authz/v1beta1/tx.proto - - - - - -### MsgExecAuthorizedRequest -MsgExecAuthorizedRequest attempts to execute the provided messages using -authorizations granted to the grantee. Each message should have only -one signer corresponding to the granter of the authorization. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `grantee` | [string](#string) | | | -| `msgs` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | - - - +## cosmos/capability/v1beta1/capability.proto - + -### MsgExecAuthorizedResponse -MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse response type. +### Capability +Capability defines an implementation of an object capability. The index +provided to a Capability must be globally unique. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | | +| `index` | [uint64](#uint64) | | | - + -### MsgGrantAuthorizationRequest -MsgGrantAuthorizationRequest grants the provided authorization to the grantee on the granter's -account with the provided expiration time. +### CapabilityOwners +CapabilityOwners defines a set of owners of a single Capability. The set of +owners must be unique. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - - - - - - - - -### MsgGrantAuthorizationResponse -MsgGrantAuthorizationResponse defines the Msg/MsgGrantAuthorization response type. +| `owners` | [Owner](#cosmos.capability.v1beta1.Owner) | repeated | | - + -### MsgRevokeAuthorizationRequest -MsgRevokeAuthorizationRequest revokes any authorization with the provided sdk.Msg type on the -granter's account with that has been granted to the grantee. +### Owner +Owner defines a single capability owner. An owner is defined by the name of +capability and the module name. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `method_name` | [string](#string) | | | - - - - - - - - -### MsgRevokeAuthorizationResponse -MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse response type. +| `module` | [string](#string) | | | +| `name` | [string](#string) | | | @@ -2871,56 +2736,43 @@ MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse re - - - -### Msg -Msg defines the authz Msg service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `GrantAuthorization` | [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) | [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) | GrantAuthorization grants the provided authorization to the grantee on the granter's account with the provided expiration time. | | -| `ExecAuthorized` | [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) | [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) | ExecAuthorized attempts to execute the provided messages using authorizations granted to the grantee. Each message should have only one signer corresponding to the granter of the authorization. | | -| `RevokeAuthorization` | [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) | [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) | RevokeAuthorization revokes any authorization corresponding to the provided method name on the granter's account that has been granted to the grantee. | | - - +

      Top

      -## cosmos/authz/v1beta1/genesis.proto +## cosmos/capability/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the authz module's genesis state. +### GenesisOwners +GenesisOwners defines the capability owners with their corresponding index. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorization` | [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) | repeated | | +| `index` | [uint64](#uint64) | | index is the index of the capability owner. | +| `index_owners` | [CapabilityOwners](#cosmos.capability.v1beta1.CapabilityOwners) | | index_owners are the owners at the given index. | - + -### GrantAuthorization -GrantAuthorization defines the GenesisState/GrantAuthorization type. +### GenesisState +GenesisState defines the capability module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `index` | [uint64](#uint64) | | index is the capability global index. | +| `owners` | [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) | repeated | owners represents a map from index to owners of the capability index index key is string to allow amino marshalling. | @@ -2936,186 +2788,165 @@ GrantAuthorization defines the GenesisState/GrantAuthorization type. - +

      Top

      -## cosmos/gov/v1beta1/gov.proto +## cosmos/crisis/v1beta1/genesis.proto - + -### Deposit -Deposit defines an amount deposited by an account address to an active -proposal. +### GenesisState +GenesisState defines the crisis module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `depositor` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `constant_fee` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | constant_fee is the fee used to verify the invariant in the crisis module. | + - + -### DepositParams -DepositParams defines the params for deposits on governance proposals. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `min_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | Minimum deposit for a proposal to enter voting period. | -| `max_deposit_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months. | + +

      Top

      +## cosmos/crisis/v1beta1/tx.proto - + -### Proposal -Proposal defines the core field members of a governance proposal. +### MsgVerifyInvariant +MsgVerifyInvariant represents a message to verify a particular invariance. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `content` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `status` | [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) | | | -| `final_tally_result` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | | -| `submit_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `deposit_end_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `total_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `voting_start_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `voting_end_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `sender` | [string](#string) | | | +| `invariant_module_name` | [string](#string) | | | +| `invariant_route` | [string](#string) | | | - + -### TallyParams -TallyParams defines the params for tallying votes on governance proposals. +### MsgVerifyInvariantResponse +MsgVerifyInvariantResponse defines the Msg/VerifyInvariant response type. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `quorum` | [bytes](#bytes) | | Minimum percentage of total stake needed to vote for a result to be considered valid. | -| `threshold` | [bytes](#bytes) | | Minimum proportion of Yes votes for proposal to pass. Default value: 0.5. | -| `veto_threshold` | [bytes](#bytes) | | Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Default value: 1/3. | + + + - -### TallyResult -TallyResult defines a standard tally for a governance proposal. + +### Msg +Msg defines the bank Msg service. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `yes` | [string](#string) | | | -| `abstain` | [string](#string) | | | -| `no` | [string](#string) | | | -| `no_with_veto` | [string](#string) | | | +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `VerifyInvariant` | [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) | [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) | VerifyInvariant defines a method to verify a particular invariance. | | + + +

      Top

      +## cosmos/crypto/ed25519/keys.proto - -### TextProposal -TextProposal defines a standard text proposal whose changes need to be -manually updated in case of approval. + + + +### PrivKey +PrivKey defines a ed25519 private key. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | +| `key` | [bytes](#bytes) | | | - + -### Vote -Vote defines a vote on a governance proposal. -A Vote consists of a proposal ID, the voter, and the vote option. +### PubKey +PubKey defines a ed25519 public key +Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte +if the y-coordinate is the lexicographically largest of the two associated with +the x-coordinate. Otherwise the first byte is a 0x03. +This prefix is followed with the x-coordinate. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `voter` | [string](#string) | | | -| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | - +| `key` | [bytes](#bytes) | | | - + -### VotingParams -VotingParams defines the params for voting on governance proposals. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `voting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Length of the voting period. | + + +

      Top

      +## cosmos/crypto/multisig/keys.proto - - + -### ProposalStatus -ProposalStatus enumerates the valid statuses of a proposal. +### LegacyAminoPubKey +LegacyAminoPubKey specifies a public key type +which nests multiple public keys and a threshold, +it uses legacy amino address rules. -| Name | Number | Description | -| ---- | ------ | ----------- | -| PROPOSAL_STATUS_UNSPECIFIED | 0 | PROPOSAL_STATUS_UNSPECIFIED defines the default propopsal status. | -| PROPOSAL_STATUS_DEPOSIT_PERIOD | 1 | PROPOSAL_STATUS_DEPOSIT_PERIOD defines a proposal status during the deposit period. | -| PROPOSAL_STATUS_VOTING_PERIOD | 2 | PROPOSAL_STATUS_VOTING_PERIOD defines a proposal status during the voting period. | -| PROPOSAL_STATUS_PASSED | 3 | PROPOSAL_STATUS_PASSED defines a proposal status of a proposal that has passed. | -| PROPOSAL_STATUS_REJECTED | 4 | PROPOSAL_STATUS_REJECTED defines a proposal status of a proposal that has been rejected. | -| PROPOSAL_STATUS_FAILED | 5 | PROPOSAL_STATUS_FAILED defines a proposal status of a proposal that has failed. | +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `threshold` | [uint32](#uint32) | | | +| `public_keys` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | - -### VoteOption -VoteOption enumerates the valid vote options for a given governance proposal. -| Name | Number | Description | -| ---- | ------ | ----------- | -| VOTE_OPTION_UNSPECIFIED | 0 | VOTE_OPTION_UNSPECIFIED defines a no-op vote option. | -| VOTE_OPTION_YES | 1 | VOTE_OPTION_YES defines a yes vote option. | -| VOTE_OPTION_ABSTAIN | 2 | VOTE_OPTION_ABSTAIN defines an abstain vote option. | -| VOTE_OPTION_NO | 3 | VOTE_OPTION_NO defines a no vote option. | -| VOTE_OPTION_NO_WITH_VETO | 4 | VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. | + @@ -3125,460 +2956,492 @@ VoteOption enumerates the valid vote options for a given governance proposal. - +

      Top

      -## cosmos/gov/v1beta1/query.proto +## cosmos/crypto/multisig/v1beta1/multisig.proto - + -### QueryDepositRequest -QueryDepositRequest is the request type for the Query/Deposit RPC method. +### CompactBitArray +CompactBitArray is an implementation of a space efficient bit array. +This is used to ensure that the encoded data takes up a minimal amount of +space after proto encoding. +This is not thread safe, and is not intended for concurrent usage. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `depositor` | [string](#string) | | depositor defines the deposit addresses from the proposals. | +| `extra_bits_stored` | [uint32](#uint32) | | | +| `elems` | [bytes](#bytes) | | | - + -### QueryDepositResponse -QueryDepositResponse is the response type for the Query/Deposit RPC method. +### MultiSignature +MultiSignature wraps the signatures from a multisig.LegacyAminoPubKey. +See cosmos.tx.v1betata1.ModeInfo.Multi for how to specify which signers +signed and with which modes. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `deposit` | [Deposit](#cosmos.gov.v1beta1.Deposit) | | deposit defines the requested deposit. | +| `signatures` | [bytes](#bytes) | repeated | | + - + -### QueryDepositsRequest -QueryDepositsRequest is the request type for the Query/Deposits RPC method. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + +

      Top

      +## cosmos/crypto/secp256k1/keys.proto - + -### QueryDepositsResponse -QueryDepositsResponse is the response type for the Query/Deposits RPC method. +### PrivKey +PrivKey defines a secp256k1 private key. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `deposits` | [Deposit](#cosmos.gov.v1beta1.Deposit) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| `key` | [bytes](#bytes) | | | - + -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. +### PubKey +PubKey defines a secp256k1 public key +Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte +if the y-coordinate is the lexicographically largest of the two associated with +the x-coordinate. Otherwise the first byte is a 0x03. +This prefix is followed with the x-coordinate. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params_type` | [string](#string) | | params_type defines which parameters to query for, can be one of "voting", "tallying" or "deposit". | +| `key` | [bytes](#bytes) | | | + - + -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `voting_params` | [VotingParams](#cosmos.gov.v1beta1.VotingParams) | | voting_params defines the parameters related to voting. | -| `deposit_params` | [DepositParams](#cosmos.gov.v1beta1.DepositParams) | | deposit_params defines the parameters related to deposit. | -| `tally_params` | [TallyParams](#cosmos.gov.v1beta1.TallyParams) | | tally_params defines the parameters related to tally. | + +

      Top

      +## cosmos/distribution/v1beta1/distribution.proto - + -### QueryProposalRequest -QueryProposalRequest is the request type for the Query/Proposal RPC method. +### CommunityPoolSpendProposal +CommunityPoolSpendProposal details a proposal for use of community funds, +together with how many coins are proposed to be spent, and to which +recipient account. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `recipient` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - + -### QueryProposalResponse -QueryProposalResponse is the response type for the Query/Proposal RPC method. +### CommunityPoolSpendProposalWithDeposit +CommunityPoolSpendProposalWithDeposit defines a CommunityPoolSpendProposal +with a deposit | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal` | [Proposal](#cosmos.gov.v1beta1.Proposal) | | | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `recipient` | [string](#string) | | | +| `amount` | [string](#string) | | | +| `deposit` | [string](#string) | | | - + -### QueryProposalsRequest -QueryProposalsRequest is the request type for the Query/Proposals RPC method. +### DelegationDelegatorReward +DelegationDelegatorReward represents the properties +of a delegator's delegation reward. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_status` | [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) | | proposal_status defines the status of the proposals. | -| `voter` | [string](#string) | | voter defines the voter address for the proposals. | -| `depositor` | [string](#string) | | depositor defines the deposit addresses from the proposals. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +| `validator_address` | [string](#string) | | | +| `reward` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - + -### QueryProposalsResponse -QueryProposalsResponse is the response type for the Query/Proposals RPC -method. +### DelegatorStartingInfo +DelegatorStartingInfo represents the starting info for a delegator reward +period. It tracks the previous validator period, the delegation's amount of +staking token, and the creation height (to check later on if any slashes have +occurred). NOTE: Even though validators are slashed to whole staking tokens, +the delegators within the validator may be left with less than a full token, +thus sdk.Dec is used. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposals` | [Proposal](#cosmos.gov.v1beta1.Proposal) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| `previous_period` | [uint64](#uint64) | | | +| `stake` | [string](#string) | | | +| `height` | [uint64](#uint64) | | | - + -### QueryTallyResultRequest -QueryTallyResultRequest is the request type for the Query/Tally RPC method. +### FeePool +FeePool is the global fee pool for distribution. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `community_pool` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - + -### QueryTallyResultResponse -QueryTallyResultResponse is the response type for the Query/Tally RPC method. +### Params +Params defines the set of params for the distribution module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `tally` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | tally defines the requested tally. | +| `community_tax` | [string](#string) | | | +| `base_proposer_reward` | [string](#string) | | | +| `bonus_proposer_reward` | [string](#string) | | | +| `withdraw_addr_enabled` | [bool](#bool) | | | - + -### QueryVoteRequest -QueryVoteRequest is the request type for the Query/Vote RPC method. +### ValidatorAccumulatedCommission +ValidatorAccumulatedCommission represents accumulated commission +for a validator kept as a running counter, can be withdrawn at any time. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `voter` | [string](#string) | | voter defines the oter address for the proposals. | +| `commission` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - + -### QueryVoteResponse -QueryVoteResponse is the response type for the Query/Vote RPC method. +### ValidatorCurrentRewards +ValidatorCurrentRewards represents current rewards and current +period for a validator kept as a running counter and incremented +each block as long as the validator's tokens remain constant. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `vote` | [Vote](#cosmos.gov.v1beta1.Vote) | | vote defined the queried vote. | +| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `period` | [uint64](#uint64) | | | - + -### QueryVotesRequest -QueryVotesRequest is the request type for the Query/Votes RPC method. +### ValidatorHistoricalRewards +ValidatorHistoricalRewards represents historical rewards for a validator. +Height is implicit within the store key. +Cumulative reward ratio is the sum from the zeroeth period +until this period of rewards / tokens, per the spec. +The reference count indicates the number of objects +which might need to reference this historical entry at any point. +ReferenceCount = + number of outstanding delegations which ended the associated period (and + might need to read that record) + + number of slashes which ended the associated period (and might need to + read that record) + + one per validator for the zeroeth period, set on initialization | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +| `cumulative_reward_ratio` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `reference_count` | [uint32](#uint32) | | | - + -### QueryVotesResponse -QueryVotesResponse is the response type for the Query/Votes RPC method. +### ValidatorOutstandingRewards +ValidatorOutstandingRewards represents outstanding (un-withdrawn) rewards +for a validator inexpensive to track, allows simple sanity checks. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `votes` | [Vote](#cosmos.gov.v1beta1.Vote) | repeated | votes defined the queried votes. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - - - - +| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - - - - -### Query -Query defines the gRPC querier service for gov module + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Proposal` | [QueryProposalRequest](#cosmos.gov.v1beta1.QueryProposalRequest) | [QueryProposalResponse](#cosmos.gov.v1beta1.QueryProposalResponse) | Proposal queries proposal details based on ProposalID. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}| -| `Proposals` | [QueryProposalsRequest](#cosmos.gov.v1beta1.QueryProposalsRequest) | [QueryProposalsResponse](#cosmos.gov.v1beta1.QueryProposalsResponse) | Proposals queries all proposals based on given status. | GET|/cosmos/gov/v1beta1/proposals| -| `Vote` | [QueryVoteRequest](#cosmos.gov.v1beta1.QueryVoteRequest) | [QueryVoteResponse](#cosmos.gov.v1beta1.QueryVoteResponse) | Vote queries voted information based on proposalID, voterAddr. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/votes/{voter}| -| `Votes` | [QueryVotesRequest](#cosmos.gov.v1beta1.QueryVotesRequest) | [QueryVotesResponse](#cosmos.gov.v1beta1.QueryVotesResponse) | Votes queries votes of a given proposal. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/votes| -| `Params` | [QueryParamsRequest](#cosmos.gov.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.gov.v1beta1.QueryParamsResponse) | Params queries all parameters of the gov module. | GET|/cosmos/gov/v1beta1/params/{params_type}| -| `Deposit` | [QueryDepositRequest](#cosmos.gov.v1beta1.QueryDepositRequest) | [QueryDepositResponse](#cosmos.gov.v1beta1.QueryDepositResponse) | Deposit queries single deposit information based proposalID, depositAddr. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits/{depositor}| -| `Deposits` | [QueryDepositsRequest](#cosmos.gov.v1beta1.QueryDepositsRequest) | [QueryDepositsResponse](#cosmos.gov.v1beta1.QueryDepositsResponse) | Deposits queries all deposits of a single proposal. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits| -| `TallyResult` | [QueryTallyResultRequest](#cosmos.gov.v1beta1.QueryTallyResultRequest) | [QueryTallyResultResponse](#cosmos.gov.v1beta1.QueryTallyResultResponse) | TallyResult queries the tally of a proposal vote. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/tally| +### ValidatorSlashEvent +ValidatorSlashEvent represents a validator slash event. +Height is implicit within the store key. +This is needed to calculate appropriate amount of staking tokens +for delegations which are withdrawn after a slash has occurred. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_period` | [uint64](#uint64) | | | +| `fraction` | [string](#string) | | | - -

      Top

      -## cosmos/gov/v1beta1/tx.proto - + -### MsgDeposit -MsgDeposit defines a message to submit a deposit to an existing proposal. +### ValidatorSlashEvents +ValidatorSlashEvents is a collection of ValidatorSlashEvent messages. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `depositor` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `validator_slash_events` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | repeated | | + - + -### MsgDepositResponse -MsgDepositResponse defines the Msg/Deposit response type. + + + + +

      Top

      +## cosmos/distribution/v1beta1/genesis.proto - -### MsgSubmitProposal -MsgSubmitProposal defines an sdk.Msg type that supports submitting arbitrary -proposal Content. + + +### DelegatorStartingInfoRecord +DelegatorStartingInfoRecord used for import / export via genesis json. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `content` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `initial_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `proposer` | [string](#string) | | | +| `delegator_address` | [string](#string) | | delegator_address is the address of the delegator. | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `starting_info` | [DelegatorStartingInfo](#cosmos.distribution.v1beta1.DelegatorStartingInfo) | | starting_info defines the starting info of a delegator. | - + -### MsgSubmitProposalResponse -MsgSubmitProposalResponse defines the Msg/SubmitProposal response type. +### DelegatorWithdrawInfo +DelegatorWithdrawInfo is the address for where distributions rewards are +withdrawn to by default this struct is only used at genesis to feed in +default withdraw addresses. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | +| `delegator_address` | [string](#string) | | delegator_address is the address of the delegator. | +| `withdraw_address` | [string](#string) | | withdraw_address is the address to withdraw the delegation rewards to. | - + -### MsgVote -MsgVote defines a message to cast a vote. +### GenesisState +GenesisState defines the distribution module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `voter` | [string](#string) | | | -| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | - - +| `params` | [Params](#cosmos.distribution.v1beta1.Params) | | params defines all the paramaters of the module. | +| `fee_pool` | [FeePool](#cosmos.distribution.v1beta1.FeePool) | | fee_pool defines the fee pool at genesis. | +| `delegator_withdraw_infos` | [DelegatorWithdrawInfo](#cosmos.distribution.v1beta1.DelegatorWithdrawInfo) | repeated | fee_pool defines the delegator withdraw infos at genesis. | +| `previous_proposer` | [string](#string) | | fee_pool defines the previous proposer at genesis. | +| `outstanding_rewards` | [ValidatorOutstandingRewardsRecord](#cosmos.distribution.v1beta1.ValidatorOutstandingRewardsRecord) | repeated | fee_pool defines the outstanding rewards of all validators at genesis. | +| `validator_accumulated_commissions` | [ValidatorAccumulatedCommissionRecord](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommissionRecord) | repeated | fee_pool defines the accumulated commisions of all validators at genesis. | +| `validator_historical_rewards` | [ValidatorHistoricalRewardsRecord](#cosmos.distribution.v1beta1.ValidatorHistoricalRewardsRecord) | repeated | fee_pool defines the historical rewards of all validators at genesis. | +| `validator_current_rewards` | [ValidatorCurrentRewardsRecord](#cosmos.distribution.v1beta1.ValidatorCurrentRewardsRecord) | repeated | fee_pool defines the current rewards of all validators at genesis. | +| `delegator_starting_infos` | [DelegatorStartingInfoRecord](#cosmos.distribution.v1beta1.DelegatorStartingInfoRecord) | repeated | fee_pool defines the delegator starting infos at genesis. | +| `validator_slash_events` | [ValidatorSlashEventRecord](#cosmos.distribution.v1beta1.ValidatorSlashEventRecord) | repeated | fee_pool defines the validator slash events at genesis. | - -### MsgVoteResponse -MsgVoteResponse defines the Msg/Vote response type. + +### ValidatorAccumulatedCommissionRecord +ValidatorAccumulatedCommissionRecord is used for import / export via genesis +json. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `accumulated` | [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) | | accumulated is the accumulated commission of a validator. | - - - - -### Msg -Msg defines the bank Msg service. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `SubmitProposal` | [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) | [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) | SubmitProposal defines a method to create new proposal given a content. | | -| `Vote` | [MsgVote](#cosmos.gov.v1beta1.MsgVote) | [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) | Vote defines a method to add a vote on a specific proposal. | | -| `Deposit` | [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) | [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) | Deposit defines a method to add deposit on a specific proposal. | | +### ValidatorCurrentRewardsRecord +ValidatorCurrentRewardsRecord is used for import / export via genesis json. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `rewards` | [ValidatorCurrentRewards](#cosmos.distribution.v1beta1.ValidatorCurrentRewards) | | rewards defines the current rewards of a validator. | - -

      Top

      -## cosmos/gov/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the gov module's genesis state. +### ValidatorHistoricalRewardsRecord +ValidatorHistoricalRewardsRecord is used for import / export via genesis +json. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `starting_proposal_id` | [uint64](#uint64) | | starting_proposal_id is the ID of the starting proposal. | -| `deposits` | [Deposit](#cosmos.gov.v1beta1.Deposit) | repeated | deposits defines all the deposits present at genesis. | -| `votes` | [Vote](#cosmos.gov.v1beta1.Vote) | repeated | votes defines all the votes present at genesis. | -| `proposals` | [Proposal](#cosmos.gov.v1beta1.Proposal) | repeated | proposals defines all the proposals present at genesis. | -| `deposit_params` | [DepositParams](#cosmos.gov.v1beta1.DepositParams) | | params defines all the paramaters of related to deposit. | -| `voting_params` | [VotingParams](#cosmos.gov.v1beta1.VotingParams) | | params defines all the paramaters of related to voting. | -| `tally_params` | [TallyParams](#cosmos.gov.v1beta1.TallyParams) | | params defines all the paramaters of related to tally. | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `period` | [uint64](#uint64) | | period defines the period the historical rewards apply to. | +| `rewards` | [ValidatorHistoricalRewards](#cosmos.distribution.v1beta1.ValidatorHistoricalRewards) | | rewards defines the historical rewards of a validator. | - - + - +### ValidatorOutstandingRewardsRecord +ValidatorOutstandingRewardsRecord is used for import/export via genesis json. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `outstanding_rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | outstanding_rewards represents the oustanding rewards of a validator. | - -

      Top

      -## cosmos/genutil/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the raw genesis transaction in JSON. +### ValidatorSlashEventRecord +ValidatorSlashEventRecord is used for import / export via genesis json. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `gen_txs` | [bytes](#bytes) | repeated | gen_txs defines the genesis transactions. | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `height` | [uint64](#uint64) | | height defines the block height at which the slash event occured. | +| `period` | [uint64](#uint64) | | period is the period of the slash event. | +| `validator_slash_event` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | | validator_slash_event describes the slash event. | @@ -3822,61 +3685,281 @@ QueryValidatorOutstandingRewardsRequest is the request type for the Query/ValidatorOutstandingRewards RPC method. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address defines the validator address to query for. | +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address defines the validator address to query for. | + + + + + + + + +### QueryValidatorOutstandingRewardsResponse +QueryValidatorOutstandingRewardsResponse is the response type for the +Query/ValidatorOutstandingRewards RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `rewards` | [ValidatorOutstandingRewards](#cosmos.distribution.v1beta1.ValidatorOutstandingRewards) | | | + + + + + + + + +### QueryValidatorSlashesRequest +QueryValidatorSlashesRequest is the request type for the +Query/ValidatorSlashes RPC method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address defines the validator address to query for. | +| `starting_height` | [uint64](#uint64) | | starting_height defines the optional starting height to query the slashes. | +| `ending_height` | [uint64](#uint64) | | starting_height defines the optional ending height to query the slashes. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + + + + + + + + +### QueryValidatorSlashesResponse +QueryValidatorSlashesResponse is the response type for the +Query/ValidatorSlashes RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `slashes` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | repeated | slashes defines the slashes the validator received. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | + + + + + + + + + + + + + + +### Query +Query defines the gRPC querier service for distribution module. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Params` | [QueryParamsRequest](#cosmos.distribution.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.distribution.v1beta1.QueryParamsResponse) | Params queries params of the distribution module. | GET|/cosmos/distribution/v1beta1/params| +| `ValidatorOutstandingRewards` | [QueryValidatorOutstandingRewardsRequest](#cosmos.distribution.v1beta1.QueryValidatorOutstandingRewardsRequest) | [QueryValidatorOutstandingRewardsResponse](#cosmos.distribution.v1beta1.QueryValidatorOutstandingRewardsResponse) | ValidatorOutstandingRewards queries rewards of a validator address. | GET|/cosmos/distribution/v1beta1/validators/{validator_address}/outstanding_rewards| +| `ValidatorCommission` | [QueryValidatorCommissionRequest](#cosmos.distribution.v1beta1.QueryValidatorCommissionRequest) | [QueryValidatorCommissionResponse](#cosmos.distribution.v1beta1.QueryValidatorCommissionResponse) | ValidatorCommission queries accumulated commission for a validator. | GET|/cosmos/distribution/v1beta1/validators/{validator_address}/commission| +| `ValidatorSlashes` | [QueryValidatorSlashesRequest](#cosmos.distribution.v1beta1.QueryValidatorSlashesRequest) | [QueryValidatorSlashesResponse](#cosmos.distribution.v1beta1.QueryValidatorSlashesResponse) | ValidatorSlashes queries slash events of a validator. | GET|/cosmos/distribution/v1beta1/validators/{validator_address}/slashes| +| `DelegationRewards` | [QueryDelegationRewardsRequest](#cosmos.distribution.v1beta1.QueryDelegationRewardsRequest) | [QueryDelegationRewardsResponse](#cosmos.distribution.v1beta1.QueryDelegationRewardsResponse) | DelegationRewards queries the total rewards accrued by a delegation. | GET|/cosmos/distribution/v1beta1/delegators/{delegator_address}/rewards/{validator_address}| +| `DelegationTotalRewards` | [QueryDelegationTotalRewardsRequest](#cosmos.distribution.v1beta1.QueryDelegationTotalRewardsRequest) | [QueryDelegationTotalRewardsResponse](#cosmos.distribution.v1beta1.QueryDelegationTotalRewardsResponse) | DelegationTotalRewards queries the total rewards accrued by a each validator. | GET|/cosmos/distribution/v1beta1/delegators/{delegator_address}/rewards| +| `DelegatorValidators` | [QueryDelegatorValidatorsRequest](#cosmos.distribution.v1beta1.QueryDelegatorValidatorsRequest) | [QueryDelegatorValidatorsResponse](#cosmos.distribution.v1beta1.QueryDelegatorValidatorsResponse) | DelegatorValidators queries the validators of a delegator. | GET|/cosmos/distribution/v1beta1/delegators/{delegator_address}/validators| +| `DelegatorWithdrawAddress` | [QueryDelegatorWithdrawAddressRequest](#cosmos.distribution.v1beta1.QueryDelegatorWithdrawAddressRequest) | [QueryDelegatorWithdrawAddressResponse](#cosmos.distribution.v1beta1.QueryDelegatorWithdrawAddressResponse) | DelegatorWithdrawAddress queries withdraw address of a delegator. | GET|/cosmos/distribution/v1beta1/delegators/{delegator_address}/withdraw_address| +| `CommunityPool` | [QueryCommunityPoolRequest](#cosmos.distribution.v1beta1.QueryCommunityPoolRequest) | [QueryCommunityPoolResponse](#cosmos.distribution.v1beta1.QueryCommunityPoolResponse) | CommunityPool queries the community pool coins. | GET|/cosmos/distribution/v1beta1/community_pool| + + + + + + +

      Top

      + +## cosmos/distribution/v1beta1/tx.proto + + + + + +### MsgFundCommunityPool +MsgFundCommunityPool allows an account to directly +fund the community pool. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `depositor` | [string](#string) | | | + + + + + + + + +### MsgFundCommunityPoolResponse +MsgFundCommunityPoolResponse defines the Msg/FundCommunityPool response type. + + + + + + + + +### MsgSetWithdrawAddress +MsgSetWithdrawAddress sets the withdraw address for +a delegator (or validator self-delegation). + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | | +| `withdraw_address` | [string](#string) | | | + + + + + + + + +### MsgSetWithdrawAddressResponse +MsgSetWithdrawAddressResponse defines the Msg/SetWithdrawAddress response type. + + + + + + + + +### MsgWithdrawDelegatorReward +MsgWithdrawDelegatorReward represents delegation withdrawal to a delegator +from a single validator. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | + + + + + + + + +### MsgWithdrawDelegatorRewardResponse +MsgWithdrawDelegatorRewardResponse defines the Msg/WithdrawDelegatorReward response type. + + + + + + + + +### MsgWithdrawValidatorCommission +MsgWithdrawValidatorCommission withdraws the full commission to the validator +address. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | | + + + + + + + + +### MsgWithdrawValidatorCommissionResponse +MsgWithdrawValidatorCommissionResponse defines the Msg/WithdrawValidatorCommission response type. + + + + + + + + + + + + + + +### Msg +Msg defines the distribution Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `SetWithdrawAddress` | [MsgSetWithdrawAddress](#cosmos.distribution.v1beta1.MsgSetWithdrawAddress) | [MsgSetWithdrawAddressResponse](#cosmos.distribution.v1beta1.MsgSetWithdrawAddressResponse) | SetWithdrawAddress defines a method to change the withdraw address for a delegator (or validator self-delegation). | | +| `WithdrawDelegatorReward` | [MsgWithdrawDelegatorReward](#cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward) | [MsgWithdrawDelegatorRewardResponse](#cosmos.distribution.v1beta1.MsgWithdrawDelegatorRewardResponse) | WithdrawDelegatorReward defines a method to withdraw rewards of delegator from a single validator. | | +| `WithdrawValidatorCommission` | [MsgWithdrawValidatorCommission](#cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission) | [MsgWithdrawValidatorCommissionResponse](#cosmos.distribution.v1beta1.MsgWithdrawValidatorCommissionResponse) | WithdrawValidatorCommission defines a method to withdraw the full commission to the validator address. | | +| `FundCommunityPool` | [MsgFundCommunityPool](#cosmos.distribution.v1beta1.MsgFundCommunityPool) | [MsgFundCommunityPoolResponse](#cosmos.distribution.v1beta1.MsgFundCommunityPoolResponse) | FundCommunityPool defines a method to allow an account to directly fund the community pool. | | + + + + +

      Top

      +## cosmos/evidence/v1beta1/evidence.proto - + -### QueryValidatorOutstandingRewardsResponse -QueryValidatorOutstandingRewardsResponse is the response type for the -Query/ValidatorOutstandingRewards RPC method. +### Equivocation +Equivocation implements the Evidence interface and defines evidence of double +signing misbehavior. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `rewards` | [ValidatorOutstandingRewards](#cosmos.distribution.v1beta1.ValidatorOutstandingRewards) | | | +| `height` | [int64](#int64) | | | +| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `power` | [int64](#int64) | | | +| `consensus_address` | [string](#string) | | | + - + -### QueryValidatorSlashesRequest -QueryValidatorSlashesRequest is the request type for the -Query/ValidatorSlashes RPC method + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address defines the validator address to query for. | -| `starting_height` | [uint64](#uint64) | | starting_height defines the optional starting height to query the slashes. | -| `ending_height` | [uint64](#uint64) | | starting_height defines the optional ending height to query the slashes. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + +

      Top

      +## cosmos/evidence/v1beta1/genesis.proto - + -### QueryValidatorSlashesResponse -QueryValidatorSlashesResponse is the response type for the -Query/ValidatorSlashes RPC method. +### GenesisState +GenesisState defines the evidence module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `slashes` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | repeated | slashes defines the slashes the validator received. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence defines all the evidence at genesis. | @@ -3888,136 +3971,133 @@ Query/ValidatorSlashes RPC method. - - - -### Query -Query defines the gRPC querier service for distribution module. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Params` | [QueryParamsRequest](#cosmos.distribution.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.distribution.v1beta1.QueryParamsResponse) | Params queries params of the distribution module. | GET|/cosmos/distribution/v1beta1/params| -| `ValidatorOutstandingRewards` | [QueryValidatorOutstandingRewardsRequest](#cosmos.distribution.v1beta1.QueryValidatorOutstandingRewardsRequest) | [QueryValidatorOutstandingRewardsResponse](#cosmos.distribution.v1beta1.QueryValidatorOutstandingRewardsResponse) | ValidatorOutstandingRewards queries rewards of a validator address. | GET|/cosmos/distribution/v1beta1/validators/{validator_address}/outstanding_rewards| -| `ValidatorCommission` | [QueryValidatorCommissionRequest](#cosmos.distribution.v1beta1.QueryValidatorCommissionRequest) | [QueryValidatorCommissionResponse](#cosmos.distribution.v1beta1.QueryValidatorCommissionResponse) | ValidatorCommission queries accumulated commission for a validator. | GET|/cosmos/distribution/v1beta1/validators/{validator_address}/commission| -| `ValidatorSlashes` | [QueryValidatorSlashesRequest](#cosmos.distribution.v1beta1.QueryValidatorSlashesRequest) | [QueryValidatorSlashesResponse](#cosmos.distribution.v1beta1.QueryValidatorSlashesResponse) | ValidatorSlashes queries slash events of a validator. | GET|/cosmos/distribution/v1beta1/validators/{validator_address}/slashes| -| `DelegationRewards` | [QueryDelegationRewardsRequest](#cosmos.distribution.v1beta1.QueryDelegationRewardsRequest) | [QueryDelegationRewardsResponse](#cosmos.distribution.v1beta1.QueryDelegationRewardsResponse) | DelegationRewards queries the total rewards accrued by a delegation. | GET|/cosmos/distribution/v1beta1/delegators/{delegator_address}/rewards/{validator_address}| -| `DelegationTotalRewards` | [QueryDelegationTotalRewardsRequest](#cosmos.distribution.v1beta1.QueryDelegationTotalRewardsRequest) | [QueryDelegationTotalRewardsResponse](#cosmos.distribution.v1beta1.QueryDelegationTotalRewardsResponse) | DelegationTotalRewards queries the total rewards accrued by a each validator. | GET|/cosmos/distribution/v1beta1/delegators/{delegator_address}/rewards| -| `DelegatorValidators` | [QueryDelegatorValidatorsRequest](#cosmos.distribution.v1beta1.QueryDelegatorValidatorsRequest) | [QueryDelegatorValidatorsResponse](#cosmos.distribution.v1beta1.QueryDelegatorValidatorsResponse) | DelegatorValidators queries the validators of a delegator. | GET|/cosmos/distribution/v1beta1/delegators/{delegator_address}/validators| -| `DelegatorWithdrawAddress` | [QueryDelegatorWithdrawAddressRequest](#cosmos.distribution.v1beta1.QueryDelegatorWithdrawAddressRequest) | [QueryDelegatorWithdrawAddressResponse](#cosmos.distribution.v1beta1.QueryDelegatorWithdrawAddressResponse) | DelegatorWithdrawAddress queries withdraw address of a delegator. | GET|/cosmos/distribution/v1beta1/delegators/{delegator_address}/withdraw_address| -| `CommunityPool` | [QueryCommunityPoolRequest](#cosmos.distribution.v1beta1.QueryCommunityPoolRequest) | [QueryCommunityPoolResponse](#cosmos.distribution.v1beta1.QueryCommunityPoolResponse) | CommunityPool queries the community pool coins. | GET|/cosmos/distribution/v1beta1/community_pool| - - +

      Top

      -## cosmos/distribution/v1beta1/tx.proto +## cosmos/evidence/v1beta1/query.proto - + -### MsgFundCommunityPool -MsgFundCommunityPool allows an account to directly -fund the community pool. +### QueryAllEvidenceRequest +QueryEvidenceRequest is the request type for the Query/AllEvidence RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `depositor` | [string](#string) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - + -### MsgFundCommunityPoolResponse -MsgFundCommunityPoolResponse defines the Msg/FundCommunityPool response type. +### QueryAllEvidenceResponse +QueryAllEvidenceResponse is the response type for the Query/AllEvidence RPC +method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence returns all evidences. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - -### MsgSetWithdrawAddress -MsgSetWithdrawAddress sets the withdraw address for -a delegator (or validator self-delegation). + + + +### QueryEvidenceRequest +QueryEvidenceRequest is the request type for the Query/Evidence RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `withdraw_address` | [string](#string) | | | - +| `evidence_hash` | [bytes](#bytes) | | evidence_hash defines the hash of the requested evidence. | - -### MsgSetWithdrawAddressResponse -MsgSetWithdrawAddressResponse defines the Msg/SetWithdrawAddress response type. + +### QueryEvidenceResponse +QueryEvidenceResponse is the response type for the Query/Evidence RPC method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | evidence returns the requested evidence. | - -### MsgWithdrawDelegatorReward -MsgWithdrawDelegatorReward represents delegation withdrawal to a delegator -from a single validator. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | + + + +### Query +Query defines the gRPC querier service. +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Evidence` | [QueryEvidenceRequest](#cosmos.evidence.v1beta1.QueryEvidenceRequest) | [QueryEvidenceResponse](#cosmos.evidence.v1beta1.QueryEvidenceResponse) | Evidence queries evidence based on evidence hash. | GET|/cosmos/evidence/v1beta1/evidence/{evidence_hash}| +| `AllEvidence` | [QueryAllEvidenceRequest](#cosmos.evidence.v1beta1.QueryAllEvidenceRequest) | [QueryAllEvidenceResponse](#cosmos.evidence.v1beta1.QueryAllEvidenceResponse) | AllEvidence queries all evidence. | GET|/cosmos/evidence/v1beta1/evidence| - + -### MsgWithdrawDelegatorRewardResponse -MsgWithdrawDelegatorRewardResponse defines the Msg/WithdrawDelegatorReward response type. + +

      Top

      +## cosmos/evidence/v1beta1/tx.proto - + -### MsgWithdrawValidatorCommission -MsgWithdrawValidatorCommission withdraws the full commission to the validator -address. +### MsgSubmitEvidence +MsgSubmitEvidence represents a message that supports submitting arbitrary +Evidence of misbehavior such as equivocation or counterfactual signing. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | | +| `submitter` | [string](#string) | | | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | | - + -### MsgWithdrawValidatorCommissionResponse -MsgWithdrawValidatorCommissionResponse defines the Msg/WithdrawValidatorCommission response type. +### MsgSubmitEvidenceResponse +MsgSubmitEvidenceResponse defines the Msg/SubmitEvidence response type. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `hash` | [bytes](#bytes) | | hash defines the hash of the evidence. | @@ -4030,167 +4110,139 @@ MsgWithdrawValidatorCommissionResponse defines the Msg/WithdrawValidatorCommissi - + ### Msg -Msg defines the distribution Msg service. +Msg defines the evidence Msg service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `SetWithdrawAddress` | [MsgSetWithdrawAddress](#cosmos.distribution.v1beta1.MsgSetWithdrawAddress) | [MsgSetWithdrawAddressResponse](#cosmos.distribution.v1beta1.MsgSetWithdrawAddressResponse) | SetWithdrawAddress defines a method to change the withdraw address for a delegator (or validator self-delegation). | | -| `WithdrawDelegatorReward` | [MsgWithdrawDelegatorReward](#cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward) | [MsgWithdrawDelegatorRewardResponse](#cosmos.distribution.v1beta1.MsgWithdrawDelegatorRewardResponse) | WithdrawDelegatorReward defines a method to withdraw rewards of delegator from a single validator. | | -| `WithdrawValidatorCommission` | [MsgWithdrawValidatorCommission](#cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission) | [MsgWithdrawValidatorCommissionResponse](#cosmos.distribution.v1beta1.MsgWithdrawValidatorCommissionResponse) | WithdrawValidatorCommission defines a method to withdraw the full commission to the validator address. | | -| `FundCommunityPool` | [MsgFundCommunityPool](#cosmos.distribution.v1beta1.MsgFundCommunityPool) | [MsgFundCommunityPoolResponse](#cosmos.distribution.v1beta1.MsgFundCommunityPoolResponse) | FundCommunityPool defines a method to allow an account to directly fund the community pool. | | +| `SubmitEvidence` | [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) | [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) | SubmitEvidence submits an arbitrary Evidence of misbehavior such as equivocation or counterfactual signing. | | - +

      Top

      -## cosmos/distribution/v1beta1/genesis.proto - - - - - -### DelegatorStartingInfoRecord -DelegatorStartingInfoRecord used for import / export via genesis json. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | delegator_address is the address of the delegator. | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `starting_info` | [DelegatorStartingInfo](#cosmos.distribution.v1beta1.DelegatorStartingInfo) | | starting_info defines the starting info of a delegator. | - - - +## cosmos/feegrant/v1beta1/feegrant.proto - + -### DelegatorWithdrawInfo -DelegatorWithdrawInfo is the address for where distributions rewards are -withdrawn to by default this struct is only used at genesis to feed in -default withdraw addresses. +### BasicFeeAllowance +BasicFeeAllowance implements FeeAllowance with a one-time grant of tokens +that optionally expires. The delegatee can use up to SpendLimit to cover fees. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | delegator_address is the address of the delegator. | -| `withdraw_address` | [string](#string) | | withdraw_address is the address to withdraw the delegation rewards to. | +| `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | spend_limit specifies the maximum amount of tokens that can be spent by this allowance and will be updated as tokens are spent. If it is empty, there is no spend limit and any amount of coins can be spent. | +| `expiration` | [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) | | expiration specifies an optional time when this allowance expires | - + -### GenesisState -GenesisState defines the distribution module's genesis state. +### Duration +Duration is a span of a clock time or number of blocks. +This is designed to be added to an ExpiresAt struct. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.distribution.v1beta1.Params) | | params defines all the paramaters of the module. | -| `fee_pool` | [FeePool](#cosmos.distribution.v1beta1.FeePool) | | fee_pool defines the fee pool at genesis. | -| `delegator_withdraw_infos` | [DelegatorWithdrawInfo](#cosmos.distribution.v1beta1.DelegatorWithdrawInfo) | repeated | fee_pool defines the delegator withdraw infos at genesis. | -| `previous_proposer` | [string](#string) | | fee_pool defines the previous proposer at genesis. | -| `outstanding_rewards` | [ValidatorOutstandingRewardsRecord](#cosmos.distribution.v1beta1.ValidatorOutstandingRewardsRecord) | repeated | fee_pool defines the outstanding rewards of all validators at genesis. | -| `validator_accumulated_commissions` | [ValidatorAccumulatedCommissionRecord](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommissionRecord) | repeated | fee_pool defines the accumulated commisions of all validators at genesis. | -| `validator_historical_rewards` | [ValidatorHistoricalRewardsRecord](#cosmos.distribution.v1beta1.ValidatorHistoricalRewardsRecord) | repeated | fee_pool defines the historical rewards of all validators at genesis. | -| `validator_current_rewards` | [ValidatorCurrentRewardsRecord](#cosmos.distribution.v1beta1.ValidatorCurrentRewardsRecord) | repeated | fee_pool defines the current rewards of all validators at genesis. | -| `delegator_starting_infos` | [DelegatorStartingInfoRecord](#cosmos.distribution.v1beta1.DelegatorStartingInfoRecord) | repeated | fee_pool defines the delegator starting infos at genesis. | -| `validator_slash_events` | [ValidatorSlashEventRecord](#cosmos.distribution.v1beta1.ValidatorSlashEventRecord) | repeated | fee_pool defines the validator slash events at genesis. | +| `duration` | [google.protobuf.Duration](#google.protobuf.Duration) | | | +| `blocks` | [uint64](#uint64) | | | - + -### ValidatorAccumulatedCommissionRecord -ValidatorAccumulatedCommissionRecord is used for import / export via genesis -json. +### ExpiresAt +ExpiresAt is a point in time where something expires. +It may be *either* block time or block height | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `accumulated` | [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) | | accumulated is the accumulated commission of a validator. | +| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `height` | [int64](#int64) | | | - + -### ValidatorCurrentRewardsRecord -ValidatorCurrentRewardsRecord is used for import / export via genesis json. +### FeeAllowanceGrant +FeeAllowanceGrant is stored in the KVStore to record a grant with full context | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `rewards` | [ValidatorCurrentRewards](#cosmos.distribution.v1beta1.ValidatorCurrentRewards) | | rewards defines the current rewards of a validator. | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | - + -### ValidatorHistoricalRewardsRecord -ValidatorHistoricalRewardsRecord is used for import / export via genesis -json. +### PeriodicFeeAllowance +PeriodicFeeAllowance extends FeeAllowance to allow for both a maximum cap, +as well as a limit per time period. | Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `period` | [uint64](#uint64) | | period defines the period the historical rewards apply to. | -| `rewards` | [ValidatorHistoricalRewards](#cosmos.distribution.v1beta1.ValidatorHistoricalRewards) | | rewards defines the historical rewards of a validator. | +| ----- | ---- | ----- | ----------- | +| `basic` | [BasicFeeAllowance](#cosmos.feegrant.v1beta1.BasicFeeAllowance) | | basic specifies a struct of `BasicFeeAllowance` | +| `period` | [Duration](#cosmos.feegrant.v1beta1.Duration) | | period specifies the time duration in which period_spend_limit coins can be spent before that allowance is reset | +| `period_spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | period_spend_limit specifies the maximum number of coins that can be spent in the period | +| `period_can_spend` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | period_can_spend is the number of coins left to be spent before the period_reset time | +| `period_reset` | [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) | | period_reset is the time at which this period resets and a new one begins, it is calculated from the start time of the first transaction after the last period ended | + - + -### ValidatorOutstandingRewardsRecord -ValidatorOutstandingRewardsRecord is used for import/export via genesis json. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `outstanding_rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | outstanding_rewards represents the oustanding rewards of a validator. | + +

      Top

      +## cosmos/feegrant/v1beta1/genesis.proto - + -### ValidatorSlashEventRecord -ValidatorSlashEventRecord is used for import / export via genesis json. +### GenesisState +GenesisState contains a set of fee allowances, persisted from the store | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `height` | [uint64](#uint64) | | height defines the block height at which the slash event occured. | -| `period` | [uint64](#uint64) | | period is the period of the slash event. | -| `validator_slash_event` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | | validator_slash_event describes the slash event. | +| `fee_allowances` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | repeated | | @@ -4206,419 +4258,419 @@ ValidatorSlashEventRecord is used for import / export via genesis json. - +

      Top

      -## cosmos/distribution/v1beta1/distribution.proto +## cosmos/feegrant/v1beta1/query.proto - + -### CommunityPoolSpendProposal -CommunityPoolSpendProposal details a proposal for use of community funds, -together with how many coins are proposed to be spent, and to which -recipient account. +### QueryFeeAllowanceRequest +QueryFeeAllowanceRequest is the request type for the Query/FeeAllowance RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `recipient` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | - + -### CommunityPoolSpendProposalWithDeposit -CommunityPoolSpendProposalWithDeposit defines a CommunityPoolSpendProposal -with a deposit +### QueryFeeAllowanceResponse +QueryFeeAllowanceResponse is the response type for the Query/FeeAllowance RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `recipient` | [string](#string) | | | -| `amount` | [string](#string) | | | -| `deposit` | [string](#string) | | | +| `fee_allowance` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | | fee_allowance is a fee_allowance granted for grantee by granter. | - + -### DelegationDelegatorReward -DelegationDelegatorReward represents the properties -of a delegator's delegation reward. +### QueryFeeAllowancesRequest +QueryFeeAllowancesRequest is the request type for the Query/FeeAllowances RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | | -| `reward` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `grantee` | [string](#string) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - + -### DelegatorStartingInfo -DelegatorStartingInfo represents the starting info for a delegator reward -period. It tracks the previous validator period, the delegation's amount of -staking token, and the creation height (to check later on if any slashes have -occurred). NOTE: Even though validators are slashed to whole staking tokens, -the delegators within the validator may be left with less than a full token, -thus sdk.Dec is used. +### QueryFeeAllowancesResponse +QueryFeeAllowancesResponse is the response type for the Query/FeeAllowances RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `previous_period` | [uint64](#uint64) | | | -| `stake` | [string](#string) | | | -| `height` | [uint64](#uint64) | | | +| `fee_allowances` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | repeated | fee_allowances are fee_allowance's granted for grantee by granter. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | + - + -### FeePool -FeePool is the global fee pool for distribution. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `community_pool` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | + + +### Query +Query defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `FeeAllowance` | [QueryFeeAllowanceRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowanceRequest) | [QueryFeeAllowanceResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowanceResponse) | FeeAllowance returns fee granted to the grantee by the granter. | GET|/cosmos/feegrant/v1beta1/fee_allowance/{granter}/{grantee}| +| `FeeAllowances` | [QueryFeeAllowancesRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowancesRequest) | [QueryFeeAllowancesResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowancesResponse) | FeeAllowances returns all the grants for address. | GET|/cosmos/feegrant/v1beta1/fee_allowances/{grantee}| + + + +

      Top

      +## cosmos/feegrant/v1beta1/tx.proto - -### Params -Params defines the set of params for the distribution module. + + +### MsgGrantFeeAllowance +MsgGrantFeeAllowance adds permission for Grantee to spend up to Allowance +of fees from the account of Granter. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `community_tax` | [string](#string) | | | -| `base_proposer_reward` | [string](#string) | | | -| `bonus_proposer_reward` | [string](#string) | | | -| `withdraw_addr_enabled` | [bool](#bool) | | | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | - + -### ValidatorAccumulatedCommission -ValidatorAccumulatedCommission represents accumulated commission -for a validator kept as a running counter, can be withdrawn at any time. +### MsgGrantFeeAllowanceResponse +MsgGrantFeeAllowanceResponse defines the Msg/GrantFeeAllowanceResponse response type. + + + + + + + + +### MsgRevokeFeeAllowance +MsgRevokeFeeAllowance removes any existing FeeAllowance from Granter to Grantee. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `commission` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | - + -### ValidatorCurrentRewards -ValidatorCurrentRewards represents current rewards and current -period for a validator kept as a running counter and incremented -each block as long as the validator's tokens remain constant. +### MsgRevokeFeeAllowanceResponse +MsgRevokeFeeAllowanceResponse defines the Msg/RevokeFeeAllowanceResponse response type. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | -| `period` | [uint64](#uint64) | | | + + + - -### ValidatorHistoricalRewards -ValidatorHistoricalRewards represents historical rewards for a validator. -Height is implicit within the store key. -Cumulative reward ratio is the sum from the zeroeth period -until this period of rewards / tokens, per the spec. -The reference count indicates the number of objects -which might need to reference this historical entry at any point. -ReferenceCount = - number of outstanding delegations which ended the associated period (and - might need to read that record) - + number of slashes which ended the associated period (and might need to - read that record) - + one per validator for the zeroeth period, set on initialization + +### Msg +Msg defines the feegrant msg service. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `cumulative_reward_ratio` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | -| `reference_count` | [uint32](#uint32) | | | +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `GrantFeeAllowance` | [MsgGrantFeeAllowance](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowance) | [MsgGrantFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowanceResponse) | GrantFeeAllowance grants fee allowance to the grantee on the granter's account with the provided expiration time. | | +| `RevokeFeeAllowance` | [MsgRevokeFeeAllowance](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowance) | [MsgRevokeFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowanceResponse) | RevokeFeeAllowance revokes any fee allowance of granter's account that has been granted to the grantee. | | + + + +

      Top

      +## cosmos/genutil/v1beta1/genesis.proto - -### ValidatorOutstandingRewards -ValidatorOutstandingRewards represents outstanding (un-withdrawn) rewards -for a validator inexpensive to track, allows simple sanity checks. + + +### GenesisState +GenesisState defines the raw genesis transaction in JSON. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `gen_txs` | [bytes](#bytes) | repeated | gen_txs defines the genesis transactions. | + - + -### ValidatorSlashEvent -ValidatorSlashEvent represents a validator slash event. -Height is implicit within the store key. -This is needed to calculate appropriate amount of staking tokens -for delegations which are withdrawn after a slash has occurred. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_period` | [uint64](#uint64) | | | -| `fraction` | [string](#string) | | | + +

      Top

      +## cosmos/gov/v1beta1/gov.proto - + -### ValidatorSlashEvents -ValidatorSlashEvents is a collection of ValidatorSlashEvent messages. +### Deposit +Deposit defines an amount deposited by an account address to an active +proposal. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_slash_events` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | repeated | | +| `proposal_id` | [uint64](#uint64) | | | +| `depositor` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - - + - +### DepositParams +DepositParams defines the params for deposits on governance proposals. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `min_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | Minimum deposit for a proposal to enter voting period. | +| `max_deposit_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months. | - -

      Top

      -## cosmos/upgrade/v1beta1/query.proto - + -### QueryAppliedPlanRequest -QueryCurrentPlanRequest is the request type for the Query/AppliedPlan RPC -method. +### Proposal +Proposal defines the core field members of a governance proposal. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | name is the name of the applied plan to query for. | +| `proposal_id` | [uint64](#uint64) | | | +| `content` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `status` | [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) | | | +| `final_tally_result` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | | +| `submit_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `deposit_end_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `total_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `voting_start_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `voting_end_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - + -### QueryAppliedPlanResponse -QueryAppliedPlanResponse is the response type for the Query/AppliedPlan RPC -method. +### TallyParams +TallyParams defines the params for tallying votes on governance proposals. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | height is the block height at which the plan was applied. | - - - - - - - - -### QueryCurrentPlanRequest -QueryCurrentPlanRequest is the request type for the Query/CurrentPlan RPC -method. +| `quorum` | [bytes](#bytes) | | Minimum percentage of total stake needed to vote for a result to be considered valid. | +| `threshold` | [bytes](#bytes) | | Minimum proportion of Yes votes for proposal to pass. Default value: 0.5. | +| `veto_threshold` | [bytes](#bytes) | | Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Default value: 1/3. | - + -### QueryCurrentPlanResponse -QueryCurrentPlanResponse is the response type for the Query/CurrentPlan RPC -method. +### TallyResult +TallyResult defines a standard tally for a governance proposal. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | plan is the current upgrade plan. | +| `yes` | [string](#string) | | | +| `abstain` | [string](#string) | | | +| `no` | [string](#string) | | | +| `no_with_veto` | [string](#string) | | | - + -### QueryUpgradedConsensusStateRequest -QueryUpgradedConsensusStateRequest is the request type for the Query/UpgradedConsensusState -RPC method. +### TextProposal +TextProposal defines a standard text proposal whose changes need to be +manually updated in case of approval. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `last_height` | [int64](#int64) | | last height of the current chain must be sent in request as this is the height under which next consensus state is stored | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | - + -### QueryUpgradedConsensusStateResponse -QueryUpgradedConsensusStateResponse is the response type for the Query/UpgradedConsensusState -RPC method. +### Vote +Vote defines a vote on a governance proposal. +A Vote consists of a proposal ID, the voter, and the vote option. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `upgraded_consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | - - - +| `proposal_id` | [uint64](#uint64) | | | +| `voter` | [string](#string) | | | +| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | - - - - + -### Query -Query defines the gRPC upgrade querier service. +### VotingParams +VotingParams defines the params for voting on governance proposals. -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `CurrentPlan` | [QueryCurrentPlanRequest](#cosmos.upgrade.v1beta1.QueryCurrentPlanRequest) | [QueryCurrentPlanResponse](#cosmos.upgrade.v1beta1.QueryCurrentPlanResponse) | CurrentPlan queries the current upgrade plan. | GET|/cosmos/upgrade/v1beta1/current_plan| -| `AppliedPlan` | [QueryAppliedPlanRequest](#cosmos.upgrade.v1beta1.QueryAppliedPlanRequest) | [QueryAppliedPlanResponse](#cosmos.upgrade.v1beta1.QueryAppliedPlanResponse) | AppliedPlan queries a previously applied upgrade plan by its name. | GET|/cosmos/upgrade/v1beta1/applied_plan/{name}| -| `UpgradedConsensusState` | [QueryUpgradedConsensusStateRequest](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateRequest) | [QueryUpgradedConsensusStateResponse](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse) | UpgradedConsensusState queries the consensus state that will serve as a trusted kernel for the next version of this chain. It will only be stored at the last height of this chain. UpgradedConsensusState RPC not supported with legacy querier | GET|/cosmos/upgrade/v1beta1/upgraded_consensus_state/{last_height}| - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `voting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Length of the voting period. | - -

      Top

      -## cosmos/upgrade/v1beta1/upgrade.proto + - + -### CancelSoftwareUpgradeProposal -CancelSoftwareUpgradeProposal is a gov Content type for cancelling a software -upgrade. +### ProposalStatus +ProposalStatus enumerates the valid statuses of a proposal. +| Name | Number | Description | +| ---- | ------ | ----------- | +| PROPOSAL_STATUS_UNSPECIFIED | 0 | PROPOSAL_STATUS_UNSPECIFIED defines the default propopsal status. | +| PROPOSAL_STATUS_DEPOSIT_PERIOD | 1 | PROPOSAL_STATUS_DEPOSIT_PERIOD defines a proposal status during the deposit period. | +| PROPOSAL_STATUS_VOTING_PERIOD | 2 | PROPOSAL_STATUS_VOTING_PERIOD defines a proposal status during the voting period. | +| PROPOSAL_STATUS_PASSED | 3 | PROPOSAL_STATUS_PASSED defines a proposal status of a proposal that has passed. | +| PROPOSAL_STATUS_REJECTED | 4 | PROPOSAL_STATUS_REJECTED defines a proposal status of a proposal that has been rejected. | +| PROPOSAL_STATUS_FAILED | 5 | PROPOSAL_STATUS_FAILED defines a proposal status of a proposal that has failed. | -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | + +### VoteOption +VoteOption enumerates the valid vote options for a given governance proposal. +| Name | Number | Description | +| ---- | ------ | ----------- | +| VOTE_OPTION_UNSPECIFIED | 0 | VOTE_OPTION_UNSPECIFIED defines a no-op vote option. | +| VOTE_OPTION_YES | 1 | VOTE_OPTION_YES defines a yes vote option. | +| VOTE_OPTION_ABSTAIN | 2 | VOTE_OPTION_ABSTAIN defines an abstain vote option. | +| VOTE_OPTION_NO | 3 | VOTE_OPTION_NO defines a no vote option. | +| VOTE_OPTION_NO_WITH_VETO | 4 | VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. | - + -### Plan -Plan specifies information about a planned upgrade and when it should occur. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | Sets the name for the upgrade. This name will be used by the upgraded version of the software to apply any special "on-upgrade" commands during the first BeginBlock method after the upgrade is applied. It is also used to detect whether a software version can handle a given upgrade. If no upgrade handler with this name has been set in the software, it will be assumed that the software is out-of-date when the upgrade Time or Height is reached and the software will exit. | -| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | The time after which the upgrade must be performed. Leave set to its zero value to use a pre-defined Height instead. | -| `height` | [int64](#int64) | | The height at which the upgrade must be performed. Only used if Time is not set. | -| `info` | [string](#string) | | Any application specific upgrade info to be included on-chain such as a git commit that validators could automatically upgrade to | -| `upgraded_client_state` | [google.protobuf.Any](#google.protobuf.Any) | | IBC-enabled chains can opt-in to including the upgraded client state in its upgrade plan This will make the chain commit to the correct upgraded (self) client state before the upgrade occurs, so that connecting chains can verify that the new upgraded client is valid by verifying a proof on the previous version of the chain. This will allow IBC connections to persist smoothly across planned chain upgrades | + +

      Top

      +## cosmos/gov/v1beta1/genesis.proto - + -### SoftwareUpgradeProposal -SoftwareUpgradeProposal is a gov Content type for initiating a software -upgrade. +### GenesisState +GenesisState defines the gov module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | | +| `starting_proposal_id` | [uint64](#uint64) | | starting_proposal_id is the ID of the starting proposal. | +| `deposits` | [Deposit](#cosmos.gov.v1beta1.Deposit) | repeated | deposits defines all the deposits present at genesis. | +| `votes` | [Vote](#cosmos.gov.v1beta1.Vote) | repeated | votes defines all the votes present at genesis. | +| `proposals` | [Proposal](#cosmos.gov.v1beta1.Proposal) | repeated | proposals defines all the proposals present at genesis. | +| `deposit_params` | [DepositParams](#cosmos.gov.v1beta1.DepositParams) | | params defines all the paramaters of related to deposit. | +| `voting_params` | [VotingParams](#cosmos.gov.v1beta1.VotingParams) | | params defines all the paramaters of related to voting. | +| `tally_params` | [TallyParams](#cosmos.gov.v1beta1.TallyParams) | | params defines all the paramaters of related to tally. | @@ -4634,297 +4686,260 @@ upgrade. - +

      Top

      -## cosmos/base/kv/v1beta1/kv.proto +## cosmos/gov/v1beta1/query.proto - + -### Pair -Pair defines a key/value bytes tuple. +### QueryDepositRequest +QueryDepositRequest is the request type for the Query/Deposit RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | -| `value` | [bytes](#bytes) | | | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `depositor` | [string](#string) | | depositor defines the deposit addresses from the proposals. | - + -### Pairs -Pairs defines a repeated slice of Pair objects. +### QueryDepositResponse +QueryDepositResponse is the response type for the Query/Deposit RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pairs` | [Pair](#cosmos.base.kv.v1beta1.Pair) | repeated | | +| `deposit` | [Deposit](#cosmos.gov.v1beta1.Deposit) | | deposit defines the requested deposit. | - - + - +### QueryDepositsRequest +QueryDepositsRequest is the request type for the Query/Deposits RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - -

      Top

      -## cosmos/base/abci/v1beta1/abci.proto - + -### ABCIMessageLog -ABCIMessageLog defines a structure containing an indexed tx ABCI message log. +### QueryDepositsResponse +QueryDepositsResponse is the response type for the Query/Deposits RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `msg_index` | [uint32](#uint32) | | | -| `log` | [string](#string) | | | -| `events` | [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) | repeated | Events contains a slice of Event objects that were emitted during some execution. | +| `deposits` | [Deposit](#cosmos.gov.v1beta1.Deposit) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - + -### Attribute -Attribute defines an attribute wrapper where the key and value are -strings instead of raw bytes. +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [string](#string) | | | -| `value` | [string](#string) | | | +| `params_type` | [string](#string) | | params_type defines which parameters to query for, can be one of "voting", "tallying" or "deposit". | - + -### GasInfo -GasInfo defines tx execution gas context. +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `gas_wanted` | [uint64](#uint64) | | GasWanted is the maximum units of work we allow this tx to perform. | -| `gas_used` | [uint64](#uint64) | | GasUsed is the amount of gas actually consumed. | +| `voting_params` | [VotingParams](#cosmos.gov.v1beta1.VotingParams) | | voting_params defines the parameters related to voting. | +| `deposit_params` | [DepositParams](#cosmos.gov.v1beta1.DepositParams) | | deposit_params defines the parameters related to deposit. | +| `tally_params` | [TallyParams](#cosmos.gov.v1beta1.TallyParams) | | tally_params defines the parameters related to tally. | - + -### MsgData -MsgData defines the data returned in a Result object during message -execution. +### QueryProposalRequest +QueryProposalRequest is the request type for the Query/Proposal RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `msg_type` | [string](#string) | | | -| `data` | [bytes](#bytes) | | | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | - + -### Result -Result is the union of ResponseFormat and ResponseCheckTx. +### QueryProposalResponse +QueryProposalResponse is the response type for the Query/Proposal RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `data` | [bytes](#bytes) | | Data is any data returned from message or handler execution. It MUST be length prefixed in order to separate data from multiple message executions. | -| `log` | [string](#string) | | Log contains the log information from message or handler execution. | -| `events` | [tendermint.abci.Event](#tendermint.abci.Event) | repeated | Events contains a slice of Event objects that were emitted during message or handler execution. | +| `proposal` | [Proposal](#cosmos.gov.v1beta1.Proposal) | | | - + -### SearchTxsResult -SearchTxsResult defines a structure for querying txs pageable +### QueryProposalsRequest +QueryProposalsRequest is the request type for the Query/Proposals RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `total_count` | [uint64](#uint64) | | Count of all txs | -| `count` | [uint64](#uint64) | | Count of txs in current page | -| `page_number` | [uint64](#uint64) | | Index of current page, start from 1 | -| `page_total` | [uint64](#uint64) | | Count of total pages | -| `limit` | [uint64](#uint64) | | Max count txs per page | -| `txs` | [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | List of txs in current page | +| `proposal_status` | [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) | | proposal_status defines the status of the proposals. | +| `voter` | [string](#string) | | voter defines the voter address for the proposals. | +| `depositor` | [string](#string) | | depositor defines the deposit addresses from the proposals. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - + -### SimulationResponse -SimulationResponse defines the response generated when a transaction is -successfully simulated. +### QueryProposalsResponse +QueryProposalsResponse is the response type for the Query/Proposals RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `gas_info` | [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | | -| `result` | [Result](#cosmos.base.abci.v1beta1.Result) | | | +| `proposals` | [Proposal](#cosmos.gov.v1beta1.Proposal) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - + -### StringEvent -StringEvent defines en Event object wrapper where all the attributes -contain key/value pairs that are strings instead of raw bytes. +### QueryTallyResultRequest +QueryTallyResultRequest is the request type for the Query/Tally RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `type` | [string](#string) | | | -| `attributes` | [Attribute](#cosmos.base.abci.v1beta1.Attribute) | repeated | | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | - + -### TxMsgData -TxMsgData defines a list of MsgData. A transaction will have a MsgData object -for each message. +### QueryTallyResultResponse +QueryTallyResultResponse is the response type for the Query/Tally RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | | +| `tally` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | tally defines the requested tally. | - + -### TxResponse -TxResponse defines a structure containing relevant tx data and metadata. The -tags are stringified and the log is JSON decoded. +### QueryVoteRequest +QueryVoteRequest is the request type for the Query/Vote RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | The block height | -| `txhash` | [string](#string) | | The transaction hash. | -| `codespace` | [string](#string) | | Namespace for the Code | -| `code` | [uint32](#uint32) | | Response code. | -| `data` | [string](#string) | | Result bytes, if any. | -| `raw_log` | [string](#string) | | The output of the application's logger (raw string). May be non-deterministic. | -| `logs` | [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) | repeated | The output of the application's logger (typed). May be non-deterministic. | -| `info` | [string](#string) | | Additional information. May be non-deterministic. | -| `gas_wanted` | [int64](#int64) | | Amount of gas requested for transaction. | -| `gas_used` | [int64](#int64) | | Amount of gas consumed by transaction. | -| `tx` | [google.protobuf.Any](#google.protobuf.Any) | | The request transaction bytes. | -| `timestamp` | [string](#string) | | Time of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time. | - +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `voter` | [string](#string) | | voter defines the oter address for the proposals. | - - - + - +### QueryVoteResponse +QueryVoteResponse is the response type for the Query/Vote RPC method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `vote` | [Vote](#cosmos.gov.v1beta1.Vote) | | vote defined the queried vote. | - -

      Top

      -## cosmos/base/query/v1beta1/pagination.proto - -### PageRequest -PageRequest is to be embedded in gRPC request messages for efficient -pagination. Ex: + - message SomeRequest { - Foo some_parameter = 1; - PageRequest pagination = 2; - } +### QueryVotesRequest +QueryVotesRequest is the request type for the Query/Votes RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | key is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be set. | -| `offset` | [uint64](#uint64) | | offset is a numeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be set. | -| `limit` | [uint64](#uint64) | | limit is the total number of results to be returned in the result page. If left empty it will default to a value to be set by each app. | -| `count_total` | [bool](#bool) | | count_total is set to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. count_total is only respected when offset is used. It is ignored when key is set. | - +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - -### PageResponse -PageResponse is to be embedded in gRPC response messages where the -corresponding request message has used PageRequest. + - message SomeResponse { - repeated Bar results = 1; - PageResponse page = 2; - } +### QueryVotesResponse +QueryVotesResponse is the response type for the Query/Votes RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `next_key` | [bytes](#bytes) | | next_key is the key to be passed to PageRequest.key to query the next page most efficiently | -| `total` | [uint64](#uint64) | | total is total number of results available if PageRequest.count_total was set, its value is undefined otherwise | +| `votes` | [Vote](#cosmos.gov.v1beta1.Vote) | repeated | votes defined the queried votes. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | @@ -4936,127 +4951,115 @@ corresponding request message has used PageRequest. - - - - - -

      Top

      - -## cosmos/base/store/v1beta1/snapshot.proto - + - +### Query +Query defines the gRPC querier service for gov module -### SnapshotIAVLItem -SnapshotIAVLItem is an exported IAVL node. +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Proposal` | [QueryProposalRequest](#cosmos.gov.v1beta1.QueryProposalRequest) | [QueryProposalResponse](#cosmos.gov.v1beta1.QueryProposalResponse) | Proposal queries proposal details based on ProposalID. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}| +| `Proposals` | [QueryProposalsRequest](#cosmos.gov.v1beta1.QueryProposalsRequest) | [QueryProposalsResponse](#cosmos.gov.v1beta1.QueryProposalsResponse) | Proposals queries all proposals based on given status. | GET|/cosmos/gov/v1beta1/proposals| +| `Vote` | [QueryVoteRequest](#cosmos.gov.v1beta1.QueryVoteRequest) | [QueryVoteResponse](#cosmos.gov.v1beta1.QueryVoteResponse) | Vote queries voted information based on proposalID, voterAddr. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/votes/{voter}| +| `Votes` | [QueryVotesRequest](#cosmos.gov.v1beta1.QueryVotesRequest) | [QueryVotesResponse](#cosmos.gov.v1beta1.QueryVotesResponse) | Votes queries votes of a given proposal. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/votes| +| `Params` | [QueryParamsRequest](#cosmos.gov.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.gov.v1beta1.QueryParamsResponse) | Params queries all parameters of the gov module. | GET|/cosmos/gov/v1beta1/params/{params_type}| +| `Deposit` | [QueryDepositRequest](#cosmos.gov.v1beta1.QueryDepositRequest) | [QueryDepositResponse](#cosmos.gov.v1beta1.QueryDepositResponse) | Deposit queries single deposit information based proposalID, depositAddr. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits/{depositor}| +| `Deposits` | [QueryDepositsRequest](#cosmos.gov.v1beta1.QueryDepositsRequest) | [QueryDepositsResponse](#cosmos.gov.v1beta1.QueryDepositsResponse) | Deposits queries all deposits of a single proposal. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits| +| `TallyResult` | [QueryTallyResultRequest](#cosmos.gov.v1beta1.QueryTallyResultRequest) | [QueryTallyResultResponse](#cosmos.gov.v1beta1.QueryTallyResultResponse) | TallyResult queries the tally of a proposal vote. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/tally| + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | -| `value` | [bytes](#bytes) | | | -| `version` | [int64](#int64) | | | -| `height` | [int32](#int32) | | | + +

      Top

      +## cosmos/gov/v1beta1/tx.proto - + -### SnapshotItem -SnapshotItem is an item contained in a rootmulti.Store snapshot. +### MsgDeposit +MsgDeposit defines a message to submit a deposit to an existing proposal. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `store` | [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) | | | -| `iavl` | [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) | | | - - +| `proposal_id` | [uint64](#uint64) | | | +| `depositor` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - -### SnapshotStoreItem -SnapshotStoreItem contains metadata about a snapshotted store. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | | +### MsgDepositResponse +MsgDepositResponse defines the Msg/Deposit response type. - - + - +### MsgSubmitProposal +MsgSubmitProposal defines an sdk.Msg type that supports submitting arbitrary +proposal Content. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `content` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `initial_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `proposer` | [string](#string) | | | - -

      Top

      -## cosmos/base/store/v1beta1/commit_info.proto - + -### CommitID -CommitID defines the committment information when a specific store is -committed. +### MsgSubmitProposalResponse +MsgSubmitProposalResponse defines the Msg/SubmitProposal response type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `version` | [int64](#int64) | | | -| `hash` | [bytes](#bytes) | | | +| `proposal_id` | [uint64](#uint64) | | | - + -### CommitInfo -CommitInfo defines commit information used by the multi-store when committing -a version/height. +### MsgVote +MsgVote defines a message to cast a vote. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `version` | [int64](#int64) | | | -| `store_infos` | [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) | repeated | | - - +| `proposal_id` | [uint64](#uint64) | | | +| `voter` | [string](#string) | | | +| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | - -### StoreInfo -StoreInfo defines store-specific commit information. It contains a reference -between a store name and the commit ID. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | | -| `commit_id` | [CommitID](#cosmos.base.store.v1beta1.CommitID) | | | +### MsgVoteResponse +MsgVoteResponse defines the Msg/Vote response type. @@ -5068,79 +5071,91 @@ between a store name and the commit ID. + + + +### Msg +Msg defines the bank Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `SubmitProposal` | [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) | [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) | SubmitProposal defines a method to create new proposal given a content. | | +| `Vote` | [MsgVote](#cosmos.gov.v1beta1.MsgVote) | [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) | Vote defines a method to add a vote on a specific proposal. | | +| `Deposit` | [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) | [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) | Deposit defines a method to add deposit on a specific proposal. | | + - +

      Top

      -## cosmos/base/v1beta1/coin.proto - +## cosmos/mint/v1beta1/mint.proto - -### Coin -Coin defines a token with a denomination and an amount. + -NOTE: The amount field is an Int which implements the custom method -signatures required by gogoproto. +### Minter +Minter represents the minting state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | | -| `amount` | [string](#string) | | | - +| `inflation` | [string](#string) | | current annual inflation rate | +| `annual_provisions` | [string](#string) | | current annual expected provisions | - -### DecCoin -DecCoin defines a token with a denomination and a decimal amount. + -NOTE: The amount field is an Dec which implements the custom method -signatures required by gogoproto. +### Params +Params holds parameters for the mint module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | | -| `amount` | [string](#string) | | | - +| `mint_denom` | [string](#string) | | type of coin to mint | +| `inflation_rate_change` | [string](#string) | | maximum annual change in inflation rate | +| `inflation_max` | [string](#string) | | maximum inflation rate | +| `inflation_min` | [string](#string) | | minimum inflation rate | +| `goal_bonded` | [string](#string) | | goal of percent bonded atoms | +| `blocks_per_year` | [uint64](#uint64) | | expected blocks per year | - + -### DecProto -DecProto defines a Protobuf wrapper around a Dec object. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `dec` | [string](#string) | | | + + +

      Top

      +## cosmos/mint/v1beta1/genesis.proto - -### IntProto -IntProto defines a Protobuf wrapper around an Int object. + + +### GenesisState +GenesisState defines the mint module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `int` | [string](#string) | | | +| `minter` | [Minter](#cosmos.mint.v1beta1.Minter) | | minter is a space for holding current inflation information. | +| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines all the paramaters of the module. | @@ -5156,236 +5171,261 @@ IntProto defines a Protobuf wrapper around an Int object. - +

      Top

      -## cosmos/base/tendermint/v1beta1/query.proto - - +## cosmos/mint/v1beta1/query.proto - -### GetBlockByHeightRequest -GetBlockByHeightRequest is the request type for the Query/GetBlockByHeight RPC method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | | +### QueryAnnualProvisionsRequest +QueryAnnualProvisionsRequest is the request type for the +Query/AnnualProvisions RPC method. - + -### GetBlockByHeightResponse -GetBlockByHeightResponse is the response type for the Query/GetBlockByHeight RPC method. +### QueryAnnualProvisionsResponse +QueryAnnualProvisionsResponse is the response type for the +Query/AnnualProvisions RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | -| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | +| `annual_provisions` | [bytes](#bytes) | | annual_provisions is the current minting annual provisions value. | - + -### GetLatestBlockRequest -GetLatestBlockRequest is the request type for the Query/GetLatestBlock RPC method. +### QueryInflationRequest +QueryInflationRequest is the request type for the Query/Inflation RPC method. - + -### GetLatestBlockResponse -GetLatestBlockResponse is the response type for the Query/GetLatestBlock RPC method. +### QueryInflationResponse +QueryInflationResponse is the response type for the Query/Inflation RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | -| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | - - +| `inflation` | [bytes](#bytes) | | inflation is the current minting inflation value. | - -### GetLatestValidatorSetRequest -GetLatestValidatorSetRequest is the request type for the Query/GetValidatorSetByHeight RPC method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. - + -### GetLatestValidatorSetResponse -GetLatestValidatorSetResponse is the response type for the Query/GetValidatorSetByHeight RPC method. +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `block_height` | [int64](#int64) | | | -| `validators` | [Validator](#cosmos.base.tendermint.v1beta1.Validator) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | +| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines the parameters of the module. | + - + -### GetNodeInfoRequest -GetNodeInfoRequest is the request type for the Query/GetNodeInfo RPC method. + + + +### Query +Query provides defines the gRPC querier service. +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Params` | [QueryParamsRequest](#cosmos.mint.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.mint.v1beta1.QueryParamsResponse) | Params returns the total set of minting parameters. | GET|/cosmos/mint/v1beta1/params| +| `Inflation` | [QueryInflationRequest](#cosmos.mint.v1beta1.QueryInflationRequest) | [QueryInflationResponse](#cosmos.mint.v1beta1.QueryInflationResponse) | Inflation returns the current minting inflation value. | GET|/cosmos/mint/v1beta1/inflation| +| `AnnualProvisions` | [QueryAnnualProvisionsRequest](#cosmos.mint.v1beta1.QueryAnnualProvisionsRequest) | [QueryAnnualProvisionsResponse](#cosmos.mint.v1beta1.QueryAnnualProvisionsResponse) | AnnualProvisions current minting annual provisions value. | GET|/cosmos/mint/v1beta1/annual_provisions| + - -### GetNodeInfoResponse -GetNodeInfoResponse is the request type for the Query/GetNodeInfo RPC method. + +

      Top

      + +## cosmos/params/v1beta1/params.proto + + + + + +### ParamChange +ParamChange defines an individual parameter change, for use in +ParameterChangeProposal. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `default_node_info` | [tendermint.p2p.DefaultNodeInfo](#tendermint.p2p.DefaultNodeInfo) | | | -| `application_version` | [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) | | | +| `subspace` | [string](#string) | | | +| `key` | [string](#string) | | | +| `value` | [string](#string) | | | - + -### GetSyncingRequest -GetSyncingRequest is the request type for the Query/GetSyncing RPC method. +### ParameterChangeProposal +ParameterChangeProposal defines a proposal to change one or more parameters. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `changes` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | repeated | | + - + -### GetSyncingResponse -GetSyncingResponse is the response type for the Query/GetSyncing RPC method. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `syncing` | [bool](#bool) | | | + + +

      Top

      + +## cosmos/params/v1beta1/query.proto - + -### GetValidatorSetByHeightRequest -GetValidatorSetByHeightRequest is the request type for the Query/GetValidatorSetByHeight RPC method. +### QueryParamsRequest +QueryParamsRequest is request type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | +| `subspace` | [string](#string) | | subspace defines the module to query the parameter for. | +| `key` | [string](#string) | | key defines the key of the parameter in the subspace. | - + -### GetValidatorSetByHeightResponse -GetValidatorSetByHeightResponse is the response type for the Query/GetValidatorSetByHeight RPC method. +### QueryParamsResponse +QueryParamsResponse is response type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `block_height` | [int64](#int64) | | | -| `validators` | [Validator](#cosmos.base.tendermint.v1beta1.Validator) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | +| `param` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | | param defines the queried parameter. | + - + -### Module -Module is the type for VersionInfo + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `path` | [string](#string) | | module path | -| `version` | [string](#string) | | module version | -| `sum` | [string](#string) | | checksum | + + +### Query +Query defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Params` | [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) | Params queries a specific parameter of a module, given its subspace and key. | GET|/cosmos/params/v1beta1/params| + + +

      Top

      +## cosmos/slashing/v1beta1/slashing.proto - -### Validator -Validator is the type for the validator-set. + + + +### Params +Params represents the parameters used for by the slashing module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `voting_power` | [int64](#int64) | | | -| `proposer_priority` | [int64](#int64) | | | +| `signed_blocks_window` | [int64](#int64) | | | +| `min_signed_per_window` | [bytes](#bytes) | | | +| `downtime_jail_duration` | [google.protobuf.Duration](#google.protobuf.Duration) | | | +| `slash_fraction_double_sign` | [bytes](#bytes) | | | +| `slash_fraction_downtime` | [bytes](#bytes) | | | - + -### VersionInfo -VersionInfo is the type for the GetNodeInfoResponse message. +### ValidatorSigningInfo +ValidatorSigningInfo defines a validator's signing info for monitoring their +liveness activity. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | | -| `app_name` | [string](#string) | | | -| `version` | [string](#string) | | | -| `git_commit` | [string](#string) | | | -| `build_tags` | [string](#string) | | | -| `go_version` | [string](#string) | | | -| `build_deps` | [Module](#cosmos.base.tendermint.v1beta1.Module) | repeated | | +| `address` | [string](#string) | | | +| `start_height` | [int64](#int64) | | Height at which validator was first a candidate OR was unjailed | +| `index_offset` | [int64](#int64) | | Index which is incremented each time the validator was a bonded in a block and may have signed a precommit or not. This in conjunction with the `SignedBlocksWindow` param determines the index in the `MissedBlocksBitArray`. | +| `jailed_until` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | Timestamp until which the validator is jailed due to liveness downtime. | +| `tombstoned` | [bool](#bool) | | Whether or not a validator has been tombstoned (killed out of validator set). It is set once the validator commits an equivocation or for any other configured misbehiavor. | +| `missed_blocks_counter` | [int64](#int64) | | A counter kept to avoid unnecessary array reads. Note that `Sum(MissedBlocksBitArray)` always equals `MissedBlocksCounter`. | @@ -5397,60 +5437,77 @@ VersionInfo is the type for the GetNodeInfoResponse message. + - -### Service -Service defines the gRPC querier service for tendermint queries. -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `GetNodeInfo` | [GetNodeInfoRequest](#cosmos.base.tendermint.v1beta1.GetNodeInfoRequest) | [GetNodeInfoResponse](#cosmos.base.tendermint.v1beta1.GetNodeInfoResponse) | GetNodeInfo queries the current node info. | GET|/cosmos/base/tendermint/v1beta1/node_info| -| `GetSyncing` | [GetSyncingRequest](#cosmos.base.tendermint.v1beta1.GetSyncingRequest) | [GetSyncingResponse](#cosmos.base.tendermint.v1beta1.GetSyncingResponse) | GetSyncing queries node syncing. | GET|/cosmos/base/tendermint/v1beta1/syncing| -| `GetLatestBlock` | [GetLatestBlockRequest](#cosmos.base.tendermint.v1beta1.GetLatestBlockRequest) | [GetLatestBlockResponse](#cosmos.base.tendermint.v1beta1.GetLatestBlockResponse) | GetLatestBlock returns the latest block. | GET|/cosmos/base/tendermint/v1beta1/blocks/latest| -| `GetBlockByHeight` | [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) | [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) | GetBlockByHeight queries block for given height. | GET|/cosmos/base/tendermint/v1beta1/blocks/{height}| -| `GetLatestValidatorSet` | [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) | [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) | GetLatestValidatorSet queries latest validator-set. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/latest| -| `GetValidatorSetByHeight` | [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) | [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) | GetValidatorSetByHeight queries validator-set at a given height. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/{height}| + +

      Top

      + +## cosmos/slashing/v1beta1/genesis.proto + + + + + +### GenesisState +GenesisState defines the slashing module's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params` | [Params](#cosmos.slashing.v1beta1.Params) | | params defines all the paramaters of related to deposit. | +| `signing_infos` | [SigningInfo](#cosmos.slashing.v1beta1.SigningInfo) | repeated | signing_infos represents a map between validator addresses and their signing infos. | +| `missed_blocks` | [ValidatorMissedBlocks](#cosmos.slashing.v1beta1.ValidatorMissedBlocks) | repeated | signing_infos represents a map between validator addresses and their missed blocks. | + + + + + + + + +### MissedBlock +MissedBlock contains height and missed status as boolean. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `index` | [int64](#int64) | | index is the height at which the block was missed. | +| `missed` | [bool](#bool) | | missed is the missed status. | - -

      Top

      -## cosmos/base/snapshots/v1beta1/snapshot.proto - + -### Metadata -Metadata contains SDK-specific snapshot metadata. +### SigningInfo +SigningInfo stores validator signing info of corresponding address. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `chunk_hashes` | [bytes](#bytes) | repeated | SHA-256 chunk hashes | +| `address` | [string](#string) | | address is the validator address. | +| `validator_signing_info` | [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) | | validator_signing_info represents the signing info of this validator. | - + -### Snapshot -Snapshot contains Tendermint state sync snapshot info. +### ValidatorMissedBlocks +ValidatorMissedBlocks contains array of missed blocks of corresponding +address. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [uint64](#uint64) | | | -| `format` | [uint32](#uint32) | | | -| `chunks` | [uint32](#uint32) | | | -| `hash` | [bytes](#bytes) | | | -| `metadata` | [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) | | | +| `address` | [string](#string) | | address is the validator address. | +| `missed_blocks` | [MissedBlock](#cosmos.slashing.v1beta1.MissedBlock) | repeated | missed_blocks is an array of missed blocks by the validator. | @@ -5466,64 +5523,97 @@ Snapshot contains Tendermint state sync snapshot info. - +

      Top

      -## cosmos/base/reflection/v1beta1/reflection.proto +## cosmos/slashing/v1beta1/query.proto - + -### ListAllInterfacesRequest -ListAllInterfacesRequest is the request type of the ListAllInterfaces RPC. +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method - + -### ListAllInterfacesResponse -ListAllInterfacesResponse is the response type of the ListAllInterfaces RPC. +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `interface_names` | [string](#string) | repeated | interface_names is an array of all the registered interfaces. | +| `params` | [Params](#cosmos.slashing.v1beta1.Params) | | | - + -### ListImplementationsRequest -ListImplementationsRequest is the request type of the ListImplementations -RPC. +### QuerySigningInfoRequest +QuerySigningInfoRequest is the request type for the Query/SigningInfo RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `interface_name` | [string](#string) | | interface_name defines the interface to query the implementations for. | +| `cons_address` | [string](#string) | | cons_address is the address to query signing info of | - + -### ListImplementationsResponse -ListImplementationsResponse is the response type of the ListImplementations -RPC. +### QuerySigningInfoResponse +QuerySigningInfoResponse is the response type for the Query/SigningInfo RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `implementation_message_names` | [string](#string) | repeated | | +| `val_signing_info` | [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) | | val_signing_info is the signing info of requested val cons address | + + + + + + + + +### QuerySigningInfosRequest +QuerySigningInfosRequest is the request type for the Query/SigningInfos RPC +method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | | + + + + + + + + +### QuerySigningInfosResponse +QuerySigningInfosResponse is the response type for the Query/SigningInfos RPC +method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `info` | [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) | repeated | info is the signing info of all validators | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | | @@ -5536,61 +5626,47 @@ RPC. - + -### ReflectionService -ReflectionService defines a service for interface reflection. +### Query +Query provides defines the gRPC querier service | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `ListAllInterfaces` | [ListAllInterfacesRequest](#cosmos.base.reflection.v1beta1.ListAllInterfacesRequest) | [ListAllInterfacesResponse](#cosmos.base.reflection.v1beta1.ListAllInterfacesResponse) | ListAllInterfaces lists all the interfaces registered in the interface registry. | GET|/cosmos/base/reflection/v1beta1/interfaces| -| `ListImplementations` | [ListImplementationsRequest](#cosmos.base.reflection.v1beta1.ListImplementationsRequest) | [ListImplementationsResponse](#cosmos.base.reflection.v1beta1.ListImplementationsResponse) | ListImplementations list all the concrete types that implement a given interface. | GET|/cosmos/base/reflection/v1beta1/interfaces/{interface_name}/implementations| +| `Params` | [QueryParamsRequest](#cosmos.slashing.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.slashing.v1beta1.QueryParamsResponse) | Params queries the parameters of slashing module | GET|/cosmos/slashing/v1beta1/params| +| `SigningInfo` | [QuerySigningInfoRequest](#cosmos.slashing.v1beta1.QuerySigningInfoRequest) | [QuerySigningInfoResponse](#cosmos.slashing.v1beta1.QuerySigningInfoResponse) | SigningInfo queries the signing info of given cons address | GET|/cosmos/slashing/v1beta1/signing_infos/{cons_address}| +| `SigningInfos` | [QuerySigningInfosRequest](#cosmos.slashing.v1beta1.QuerySigningInfosRequest) | [QuerySigningInfosResponse](#cosmos.slashing.v1beta1.QuerySigningInfosResponse) | SigningInfos queries signing info of all validators | GET|/cosmos/slashing/v1beta1/signing_infos| - +

      Top

      -## cosmos/slashing/v1beta1/slashing.proto +## cosmos/slashing/v1beta1/tx.proto - + -### Params -Params represents the parameters used for by the slashing module. +### MsgUnjail +MsgUnjail defines the Msg/Unjail request type | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `signed_blocks_window` | [int64](#int64) | | | -| `min_signed_per_window` | [bytes](#bytes) | | | -| `downtime_jail_duration` | [google.protobuf.Duration](#google.protobuf.Duration) | | | -| `slash_fraction_double_sign` | [bytes](#bytes) | | | -| `slash_fraction_downtime` | [bytes](#bytes) | | | - - +| `validator_addr` | [string](#string) | | | - -### ValidatorSigningInfo -ValidatorSigningInfo defines a validator's signing info for monitoring their -liveness activity. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `start_height` | [int64](#int64) | | Height at which validator was first a candidate OR was unjailed | -| `index_offset` | [int64](#int64) | | Index which is incremented each time the validator was a bonded in a block and may have signed a precommit or not. This in conjunction with the `SignedBlocksWindow` param determines the index in the `MissedBlocksBitArray`. | -| `jailed_until` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | Timestamp until which the validator is jailed due to liveness downtime. | -| `tombstoned` | [bool](#bool) | | Whether or not a validator has been tombstoned (killed out of validator set). It is set once the validator commits an equivocation or for any other configured misbehiavor. | -| `missed_blocks_counter` | [int64](#int64) | | A counter kept to avoid unnecessary array reads. Note that `Sum(MissedBlocksBitArray)` always equals `MissedBlocksCounter`. | +### MsgUnjailResponse +MsgUnjailResponse defines the Msg/Unjail response type @@ -5602,360 +5678,461 @@ liveness activity. + + + +### Msg +Msg defines the slashing Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Unjail` | [MsgUnjail](#cosmos.slashing.v1beta1.MsgUnjail) | [MsgUnjailResponse](#cosmos.slashing.v1beta1.MsgUnjailResponse) | Unjail defines a method for unjailing a jailed validator, thus returning them into the bonded validator set, so they can begin receiving provisions and rewards again. | | + - +

      Top

      -## cosmos/slashing/v1beta1/query.proto +## cosmos/staking/v1beta1/staking.proto - + -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method +### Commission +Commission defines commission parameters for a given validator. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `commission_rates` | [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) | | commission_rates defines the initial commission rates to be used for creating a validator. | +| `update_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | update_time is the last time the commission rate was changed. | - -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method + + + +### CommissionRates +CommissionRates defines the initial commission rates to be used for creating +a validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.slashing.v1beta1.Params) | | | +| `rate` | [string](#string) | | rate is the commission rate charged to delegators, as a fraction. | +| `max_rate` | [string](#string) | | max_rate defines the maximum commission rate which validator can ever charge, as a fraction. | +| `max_change_rate` | [string](#string) | | max_change_rate defines the maximum daily increase of the validator commission, as a fraction. | - + -### QuerySigningInfoRequest -QuerySigningInfoRequest is the request type for the Query/SigningInfo RPC -method +### DVPair +DVPair is struct that just has a delegator-validator pair with no other data. +It is intended to be used as a marshalable pointer. For example, a DVPair can +be used to construct the key to getting an UnbondingDelegation from state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `cons_address` | [string](#string) | | cons_address is the address to query signing info of | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | - + -### QuerySigningInfoResponse -QuerySigningInfoResponse is the response type for the Query/SigningInfo RPC -method +### DVPairs +DVPairs defines an array of DVPair objects. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `val_signing_info` | [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) | | val_signing_info is the signing info of requested val cons address | +| `pairs` | [DVPair](#cosmos.staking.v1beta1.DVPair) | repeated | | - + -### QuerySigningInfosRequest -QuerySigningInfosRequest is the request type for the Query/SigningInfos RPC -method +### DVVTriplet +DVVTriplet is struct that just has a delegator-validator-validator triplet +with no other data. It is intended to be used as a marshalable pointer. For +example, a DVVTriplet can be used to construct the key to getting a +Redelegation from state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | | +| `delegator_address` | [string](#string) | | | +| `validator_src_address` | [string](#string) | | | +| `validator_dst_address` | [string](#string) | | | - + -### QuerySigningInfosResponse -QuerySigningInfosResponse is the response type for the Query/SigningInfos RPC -method +### DVVTriplets +DVVTriplets defines an array of DVVTriplet objects. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `info` | [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) | repeated | info is the signing info of all validators | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | | +| `triplets` | [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) | repeated | | - - + + +### Delegation +Delegation represents the bond with tokens held by an account. It is +owned by one delegator, and is associated with the voting power of one +validator. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | delegator_address is the bech32-encoded address of the delegator. | +| `validator_address` | [string](#string) | | validator_address is the bech32-encoded address of the validator. | +| `shares` | [string](#string) | | shares define the delegation shares received. | + + + + + + + + +### DelegationResponse +DelegationResponse is equivalent to Delegation except that it contains a +balance in addition to shares which is more suitable for client responses. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegation` | [Delegation](#cosmos.staking.v1beta1.Delegation) | | | +| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | + + - - -### Query -Query provides defines the gRPC querier service + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Params` | [QueryParamsRequest](#cosmos.slashing.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.slashing.v1beta1.QueryParamsResponse) | Params queries the parameters of slashing module | GET|/cosmos/slashing/v1beta1/params| -| `SigningInfo` | [QuerySigningInfoRequest](#cosmos.slashing.v1beta1.QuerySigningInfoRequest) | [QuerySigningInfoResponse](#cosmos.slashing.v1beta1.QuerySigningInfoResponse) | SigningInfo queries the signing info of given cons address | GET|/cosmos/slashing/v1beta1/signing_infos/{cons_address}| -| `SigningInfos` | [QuerySigningInfosRequest](#cosmos.slashing.v1beta1.QuerySigningInfosRequest) | [QuerySigningInfosResponse](#cosmos.slashing.v1beta1.QuerySigningInfosResponse) | SigningInfos queries signing info of all validators | GET|/cosmos/slashing/v1beta1/signing_infos| +### Description +Description defines a validator description. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `moniker` | [string](#string) | | moniker defines a human-readable name for the validator. | +| `identity` | [string](#string) | | identity defines an optional identity signature (ex. UPort or Keybase). | +| `website` | [string](#string) | | website defines an optional website link. | +| `security_contact` | [string](#string) | | security_contact defines an optional email for security contact. | +| `details` | [string](#string) | | details define other optional details. | - -

      Top

      -## cosmos/slashing/v1beta1/tx.proto - + -### MsgUnjail -MsgUnjail defines the Msg/Unjail request type +### HistoricalInfo +HistoricalInfo contains header and validator information for a given block. +It is stored as part of staking module's state, which persists the `n` most +recent HistoricalInfo +(`n` is set by the staking module's `historical_entries` parameter). | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_addr` | [string](#string) | | | - - +| `header` | [tendermint.types.Header](#tendermint.types.Header) | | | +| `valset` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | | - -### MsgUnjailResponse -MsgUnjailResponse defines the Msg/Unjail response type + +### Params +Params defines the parameters for the staking module. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `unbonding_time` | [google.protobuf.Duration](#google.protobuf.Duration) | | unbonding_time is the time duration of unbonding. | +| `max_validators` | [uint32](#uint32) | | max_validators is the maximum number of validators. | +| `max_entries` | [uint32](#uint32) | | max_entries is the max entries for either unbonding delegation or redelegation (per pair/trio). | +| `historical_entries` | [uint32](#uint32) | | historical_entries is the number of historical entries to persist. | +| `bond_denom` | [string](#string) | | bond_denom defines the bondable coin denomination. | - - - - -### Msg -Msg defines the slashing Msg service. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Unjail` | [MsgUnjail](#cosmos.slashing.v1beta1.MsgUnjail) | [MsgUnjailResponse](#cosmos.slashing.v1beta1.MsgUnjailResponse) | Unjail defines a method for unjailing a jailed validator, thus returning them into the bonded validator set, so they can begin receiving provisions and rewards again. | | +### Pool +Pool is used for tracking bonded and not-bonded token supply of the bond +denomination. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `not_bonded_tokens` | [string](#string) | | | +| `bonded_tokens` | [string](#string) | | | - -

      Top

      -## cosmos/slashing/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the slashing module's genesis state. +### Redelegation +Redelegation contains the list of a particular delegator's redelegating bonds +from a particular source validator to a particular destination validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.slashing.v1beta1.Params) | | params defines all the paramaters of related to deposit. | -| `signing_infos` | [SigningInfo](#cosmos.slashing.v1beta1.SigningInfo) | repeated | signing_infos represents a map between validator addresses and their signing infos. | -| `missed_blocks` | [ValidatorMissedBlocks](#cosmos.slashing.v1beta1.ValidatorMissedBlocks) | repeated | signing_infos represents a map between validator addresses and their missed blocks. | +| `delegator_address` | [string](#string) | | delegator_address is the bech32-encoded address of the delegator. | +| `validator_src_address` | [string](#string) | | validator_src_address is the validator redelegation source operator address. | +| `validator_dst_address` | [string](#string) | | validator_dst_address is the validator redelegation destination operator address. | +| `entries` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | repeated | entries are the redelegation entries. +redelegation entries | - -### MissedBlock -MissedBlock contains height and missed status as boolean. + + +### RedelegationEntry +RedelegationEntry defines a redelegation object with relevant metadata. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `index` | [int64](#int64) | | index is the height at which the block was missed. | -| `missed` | [bool](#bool) | | missed is the missed status. | +| `creation_height` | [int64](#int64) | | creation_height defines the height which the redelegation took place. | +| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | completion_time defines the unix time for redelegation completion. | +| `initial_balance` | [string](#string) | | initial_balance defines the initial balance when redelegation started. | +| `shares_dst` | [string](#string) | | shares_dst is the amount of destination-validator shares created by redelegation. | - + -### SigningInfo -SigningInfo stores validator signing info of corresponding address. +### RedelegationEntryResponse +RedelegationEntryResponse is equivalent to a RedelegationEntry except that it +contains a balance in addition to shares which is more suitable for client +responses. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the validator address. | -| `validator_signing_info` | [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) | | validator_signing_info represents the signing info of this validator. | +| `redelegation_entry` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | | | +| `balance` | [string](#string) | | | - + -### ValidatorMissedBlocks -ValidatorMissedBlocks contains array of missed blocks of corresponding -address. +### RedelegationResponse +RedelegationResponse is equivalent to a Redelegation except that its entries +contain a balance in addition to shares which is more suitable for client +responses. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the validator address. | -| `missed_blocks` | [MissedBlock](#cosmos.slashing.v1beta1.MissedBlock) | repeated | missed_blocks is an array of missed blocks by the validator. | +| `redelegation` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | | | +| `entries` | [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) | repeated | | - - + - +### UnbondingDelegation +UnbondingDelegation stores all of a single delegator's unbonding bonds +for a single validator in an time-ordered list. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | delegator_address is the bech32-encoded address of the delegator. | +| `validator_address` | [string](#string) | | validator_address is the bech32-encoded address of the validator. | +| `entries` | [UnbondingDelegationEntry](#cosmos.staking.v1beta1.UnbondingDelegationEntry) | repeated | entries are the unbonding delegation entries. +unbonding delegation entries | - -

      Top

      -## cosmos/evidence/v1beta1/evidence.proto - -### Equivocation -Equivocation implements the Evidence interface and defines evidence of double -signing misbehavior. + + +### UnbondingDelegationEntry +UnbondingDelegationEntry defines an unbonding object with relevant metadata. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | | -| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `power` | [int64](#int64) | | | -| `consensus_address` | [string](#string) | | | +| `creation_height` | [int64](#int64) | | creation_height is the height which the unbonding took place. | +| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | completion_time is the unix time for unbonding completion. | +| `initial_balance` | [string](#string) | | initial_balance defines the tokens initially scheduled to receive at completion. | +| `balance` | [string](#string) | | balance defines the tokens to receive at completion. | - - + - +### ValAddresses +ValAddresses defines a repeated set of validator addresses. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `addresses` | [string](#string) | repeated | | - -

      Top

      -## cosmos/evidence/v1beta1/query.proto - + -### QueryAllEvidenceRequest -QueryEvidenceRequest is the request type for the Query/AllEvidence RPC -method. +### Validator +Validator defines a validator, together with the total amount of the +Validator's bond shares and their exchange rate to coins. Slashing results in +a decrease in the exchange rate, allowing correct calculation of future +undelegations without iterating over delegators. When coins are delegated to +this validator, the validator is credited with a delegation whose number of +bond shares is based on the amount of coins delegated divided by the current +exchange rate. Voting power can be calculated as total bonded shares +multiplied by exchange rate. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +| `operator_address` | [string](#string) | | operator_address defines the address of the validator's operator; bech encoded in JSON. | +| `consensus_pubkey` | [google.protobuf.Any](#google.protobuf.Any) | | consensus_pubkey is the consensus public key of the validator, as a Protobuf Any. | +| `jailed` | [bool](#bool) | | jailed defined whether the validator has been jailed from bonded status or not. | +| `status` | [BondStatus](#cosmos.staking.v1beta1.BondStatus) | | status is the validator status (bonded/unbonding/unbonded). | +| `tokens` | [string](#string) | | tokens define the delegated tokens (incl. self-delegation). | +| `delegator_shares` | [string](#string) | | delegator_shares defines total shares issued to a validator's delegators. | +| `description` | [Description](#cosmos.staking.v1beta1.Description) | | description defines the description terms for the validator. | +| `unbonding_height` | [int64](#int64) | | unbonding_height defines, if unbonding, the height at which this validator has begun unbonding. | +| `unbonding_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | unbonding_time defines, if unbonding, the min time for the validator to complete unbonding. | +| `commission` | [Commission](#cosmos.staking.v1beta1.Commission) | | commission defines the commission parameters. | +| `min_self_delegation` | [string](#string) | | min_self_delegation is the validator's self declared minimum self delegation. | + - -### QueryAllEvidenceResponse -QueryAllEvidenceResponse is the response type for the Query/AllEvidence RPC -method. + +### BondStatus +BondStatus is the status of a validator. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence returns all evidences. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| Name | Number | Description | +| ---- | ------ | ----------- | +| BOND_STATUS_UNSPECIFIED | 0 | UNSPECIFIED defines an invalid validator status. | +| BOND_STATUS_UNBONDED | 1 | UNBONDED defines a validator that is not bonded. | +| BOND_STATUS_UNBONDING | 2 | UNBONDING defines a validator that is unbonding. | +| BOND_STATUS_BONDED | 3 | BONDED defines a validator that is bonded. | + + + - -### QueryEvidenceRequest -QueryEvidenceRequest is the request type for the Query/Evidence RPC method. + +

      Top

      + +## cosmos/staking/v1beta1/genesis.proto + + + + + +### GenesisState +GenesisState defines the staking module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `evidence_hash` | [bytes](#bytes) | | evidence_hash defines the hash of the requested evidence. | +| `params` | [Params](#cosmos.staking.v1beta1.Params) | | params defines all the paramaters of related to deposit. | +| `last_total_power` | [bytes](#bytes) | | last_total_power tracks the total amounts of bonded tokens recorded during the previous end block. | +| `last_validator_powers` | [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) | repeated | last_validator_powers is a special index that provides a historical list of the last-block's bonded validators. | +| `validators` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | delegations defines the validator set at genesis. | +| `delegations` | [Delegation](#cosmos.staking.v1beta1.Delegation) | repeated | delegations defines the delegations active at genesis. | +| `unbonding_delegations` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | repeated | unbonding_delegations defines the unbonding delegations active at genesis. | +| `redelegations` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | repeated | redelegations defines the redelegations active at genesis. | +| `exported` | [bool](#bool) | | | - + -### QueryEvidenceResponse -QueryEvidenceResponse is the response type for the Query/Evidence RPC method. +### LastValidatorPower +LastValidatorPower required for validator set update logic. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | evidence returns the requested evidence. | +| `address` | [string](#string) | | address is the address of the validator. | +| `power` | [int64](#int64) | | power defines the power of the validator. | @@ -5967,307 +6144,306 @@ QueryEvidenceResponse is the response type for the Query/Evidence RPC method. - - - -### Query -Query defines the gRPC querier service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Evidence` | [QueryEvidenceRequest](#cosmos.evidence.v1beta1.QueryEvidenceRequest) | [QueryEvidenceResponse](#cosmos.evidence.v1beta1.QueryEvidenceResponse) | Evidence queries evidence based on evidence hash. | GET|/cosmos/evidence/v1beta1/evidence/{evidence_hash}| -| `AllEvidence` | [QueryAllEvidenceRequest](#cosmos.evidence.v1beta1.QueryAllEvidenceRequest) | [QueryAllEvidenceResponse](#cosmos.evidence.v1beta1.QueryAllEvidenceResponse) | AllEvidence queries all evidence. | GET|/cosmos/evidence/v1beta1/evidence| - - +

      Top

      -## cosmos/evidence/v1beta1/tx.proto +## cosmos/staking/v1beta1/query.proto - + -### MsgSubmitEvidence -MsgSubmitEvidence represents a message that supports submitting arbitrary -Evidence of misbehavior such as equivocation or counterfactual signing. +### QueryDelegationRequest +QueryDelegationRequest is request type for the Query/Delegation RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `submitter` | [string](#string) | | | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `delegator_addr` | [string](#string) | | delegator_addr defines the delegator address to query for. | +| `validator_addr` | [string](#string) | | validator_addr defines the validator address to query for. | - + -### MsgSubmitEvidenceResponse -MsgSubmitEvidenceResponse defines the Msg/SubmitEvidence response type. +### QueryDelegationResponse +QueryDelegationResponse is response type for the Query/Delegation RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `hash` | [bytes](#bytes) | | hash defines the hash of the evidence. | +| `delegation_response` | [DelegationResponse](#cosmos.staking.v1beta1.DelegationResponse) | | delegation_responses defines the delegation info of a delegation. | + + + + + +### QueryDelegatorDelegationsRequest +QueryDelegatorDelegationsRequest is request type for the +Query/DelegatorDelegations RPC method. + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_addr` | [string](#string) | | delegator_addr defines the delegator address to query for. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - - - - -### Msg -Msg defines the evidence Msg service. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `SubmitEvidence` | [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) | [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) | SubmitEvidence submits an arbitrary Evidence of misbehavior such as equivocation or counterfactual signing. | | +### QueryDelegatorDelegationsResponse +QueryDelegatorDelegationsResponse is response type for the +Query/DelegatorDelegations RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegation_responses` | [DelegationResponse](#cosmos.staking.v1beta1.DelegationResponse) | repeated | delegation_responses defines all the delegations' info of a delegator. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - -

      Top

      -## cosmos/evidence/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the evidence module's genesis state. +### QueryDelegatorUnbondingDelegationsRequest +QueryDelegatorUnbondingDelegationsRequest is request type for the +Query/DelegatorUnbondingDelegations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence defines all the evidence at genesis. | +| `delegator_addr` | [string](#string) | | delegator_addr defines the delegator address to query for. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - - + - +### QueryDelegatorUnbondingDelegationsResponse +QueryUnbondingDelegatorDelegationsResponse is response type for the +Query/UnbondingDelegatorDelegations RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `unbonding_responses` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - -

      Top

      -## cosmos/auth/v1beta1/auth.proto - + -### BaseAccount -BaseAccount defines a base account type. It contains all the necessary fields -for basic account functionality. Any custom account type should extend this -type for additional functionality (e.g. vesting). +### QueryDelegatorValidatorRequest +QueryDelegatorValidatorRequest is request type for the +Query/DelegatorValidator RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `account_number` | [uint64](#uint64) | | | -| `sequence` | [uint64](#uint64) | | | +| `delegator_addr` | [string](#string) | | delegator_addr defines the delegator address to query for. | +| `validator_addr` | [string](#string) | | validator_addr defines the validator address to query for. | - + -### ModuleAccount -ModuleAccount defines an account for modules that holds coins on a pool. +### QueryDelegatorValidatorResponse +QueryDelegatorValidatorResponse response type for the +Query/DelegatorValidator RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `base_account` | [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) | | | -| `name` | [string](#string) | | | -| `permissions` | [string](#string) | repeated | | +| `validator` | [Validator](#cosmos.staking.v1beta1.Validator) | | validator defines the the validator info. | - + -### Params -Params defines the parameters for the auth module. +### QueryDelegatorValidatorsRequest +QueryDelegatorValidatorsRequest is request type for the +Query/DelegatorValidators RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `max_memo_characters` | [uint64](#uint64) | | | -| `tx_sig_limit` | [uint64](#uint64) | | | -| `tx_size_cost_per_byte` | [uint64](#uint64) | | | -| `sig_verify_cost_ed25519` | [uint64](#uint64) | | | -| `sig_verify_cost_secp256k1` | [uint64](#uint64) | | | +| `delegator_addr` | [string](#string) | | delegator_addr defines the delegator address to query for. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - - + - +### QueryDelegatorValidatorsResponse +QueryDelegatorValidatorsResponse is response type for the +Query/DelegatorValidators RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validators` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | validators defines the the validators' info of a delegator. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - -

      Top

      -## cosmos/auth/v1beta1/query.proto - + -### QueryAccountRequest -QueryAccountRequest is the request type for the Query/Account RPC method. +### QueryHistoricalInfoRequest +QueryHistoricalInfoRequest is request type for the Query/HistoricalInfo RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address defines the address to query for. | +| `height` | [int64](#int64) | | height defines at which height to query the historical info. | - + -### QueryAccountResponse -QueryAccountResponse is the response type for the Query/Account RPC method. +### QueryHistoricalInfoResponse +QueryHistoricalInfoResponse is response type for the Query/HistoricalInfo RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `account` | [google.protobuf.Any](#google.protobuf.Any) | | account defines the account of the corresponding address. | +| `hist` | [HistoricalInfo](#cosmos.staking.v1beta1.HistoricalInfo) | | hist defines the historical info at the given height. | - + ### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. +QueryParamsRequest is request type for the Query/Params RPC method. - + ### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method. +QueryParamsResponse is response type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines the parameters of the module. | +| `params` | [Params](#cosmos.staking.v1beta1.Params) | | params holds all the parameters of this module. | - - + - +### QueryPoolRequest +QueryPoolRequest is request type for the Query/Pool RPC method. - -### Query -Query defines the gRPC querier service. -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Account` | [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) | [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) | Account returns account details based on address. | GET|/cosmos/auth/v1beta1/accounts/{address}| -| `Params` | [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) | Params queries all parameters. | GET|/cosmos/auth/v1beta1/params| - + +### QueryPoolResponse +QueryPoolResponse is response type for the Query/Pool RPC method. - -

      Top

      -## cosmos/auth/v1beta1/genesis.proto +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `pool` | [Pool](#cosmos.staking.v1beta1.Pool) | | pool defines the pool info. | - -### GenesisState -GenesisState defines the auth module's genesis state. + + + + +### QueryRedelegationsRequest +QueryRedelegationsRequest is request type for the Query/Redelegations RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines all the paramaters of the module. | -| `accounts` | [google.protobuf.Any](#google.protobuf.Any) | repeated | accounts are the accounts present at genesis. | +| `delegator_addr` | [string](#string) | | delegator_addr defines the delegator address to query for. | +| `src_validator_addr` | [string](#string) | | src_validator_addr defines the validator address to redelegate from. | +| `dst_validator_addr` | [string](#string) | | dst_validator_addr defines the validator address to redelegate to. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - - + - +### QueryRedelegationsResponse +QueryRedelegationsResponse is response type for the Query/Redelegations RPC +method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `redelegation_responses` | [RedelegationResponse](#cosmos.staking.v1beta1.RedelegationResponse) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - -

      Top

      -## cosmos/staking/v1beta1/query.proto - + -### QueryDelegationRequest -QueryDelegationRequest is request type for the Query/Delegation RPC method. +### QueryUnbondingDelegationRequest +QueryUnbondingDelegationRequest is request type for the +Query/UnbondingDelegation RPC method. | Field | Type | Label | Description | @@ -6280,31 +6456,32 @@ QueryDelegationRequest is request type for the Query/Delegation RPC method. - + -### QueryDelegationResponse -QueryDelegationResponse is response type for the Query/Delegation RPC method. +### QueryUnbondingDelegationResponse +QueryDelegationResponse is response type for the Query/UnbondingDelegation +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegation_response` | [DelegationResponse](#cosmos.staking.v1beta1.DelegationResponse) | | delegation_responses defines the delegation info of a delegation. | +| `unbond` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | | unbond defines the unbonding information of a delegation. | - + -### QueryDelegatorDelegationsRequest -QueryDelegatorDelegationsRequest is request type for the -Query/DelegatorDelegations RPC method. +### QueryValidatorDelegationsRequest +QueryValidatorDelegationsRequest is request type for the +Query/ValidatorDelegations RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_addr` | [string](#string) | | delegator_addr defines the delegator address to query for. | +| `validator_addr` | [string](#string) | | validator_addr defines the validator address to query for. | | `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | @@ -6312,16 +6489,16 @@ Query/DelegatorDelegations RPC method. - + -### QueryDelegatorDelegationsResponse -QueryDelegatorDelegationsResponse is response type for the -Query/DelegatorDelegations RPC method. +### QueryValidatorDelegationsResponse +QueryValidatorDelegationsResponse is response type for the +Query/ValidatorDelegations RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegation_responses` | [DelegationResponse](#cosmos.staking.v1beta1.DelegationResponse) | repeated | delegation_responses defines all the delegations' info of a delegator. | +| `delegation_responses` | [DelegationResponse](#cosmos.staking.v1beta1.DelegationResponse) | repeated | | | `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | @@ -6329,83 +6506,79 @@ Query/DelegatorDelegations RPC method. - + -### QueryDelegatorUnbondingDelegationsRequest -QueryDelegatorUnbondingDelegationsRequest is request type for the -Query/DelegatorUnbondingDelegations RPC method. +### QueryValidatorRequest +QueryValidatorRequest is response type for the Query/Validator RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_addr` | [string](#string) | | delegator_addr defines the delegator address to query for. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +| `validator_addr` | [string](#string) | | validator_addr defines the validator address to query for. | - + -### QueryDelegatorUnbondingDelegationsResponse -QueryUnbondingDelegatorDelegationsResponse is response type for the -Query/UnbondingDelegatorDelegations RPC method. +### QueryValidatorResponse +QueryValidatorResponse is response type for the Query/Validator RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `unbonding_responses` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| `validator` | [Validator](#cosmos.staking.v1beta1.Validator) | | validator defines the the validator info. | - + -### QueryDelegatorValidatorRequest -QueryDelegatorValidatorRequest is request type for the -Query/DelegatorValidator RPC method. +### QueryValidatorUnbondingDelegationsRequest +QueryValidatorUnbondingDelegationsRequest is required type for the +Query/ValidatorUnbondingDelegations RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_addr` | [string](#string) | | delegator_addr defines the delegator address to query for. | | `validator_addr` | [string](#string) | | validator_addr defines the validator address to query for. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - - -### QueryDelegatorValidatorResponse -QueryDelegatorValidatorResponse response type for the -Query/DelegatorValidator RPC method. + + +### QueryValidatorUnbondingDelegationsResponse +QueryValidatorUnbondingDelegationsResponse is response type for the +Query/ValidatorUnbondingDelegations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator` | [Validator](#cosmos.staking.v1beta1.Validator) | | validator defines the the validator info. | +| `unbonding_responses` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - + -### QueryDelegatorValidatorsRequest -QueryDelegatorValidatorsRequest is request type for the -Query/DelegatorValidators RPC method. +### QueryValidatorsRequest +QueryValidatorsRequest is request type for Query/Validators RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_addr` | [string](#string) | | delegator_addr defines the delegator address to query for. | +| `status` | [string](#string) | | status enables to query for validators matching a given status. | | `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | @@ -6413,298 +6586,322 @@ Query/DelegatorValidators RPC method. - + -### QueryDelegatorValidatorsResponse -QueryDelegatorValidatorsResponse is response type for the -Query/DelegatorValidators RPC method. +### QueryValidatorsResponse +QueryValidatorsResponse is response type for the Query/Validators RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validators` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | validators defines the the validators' info of a delegator. | +| `validators` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | validators contains all the queried validators. | | `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | + - - -### QueryHistoricalInfoRequest -QueryHistoricalInfoRequest is request type for the Query/HistoricalInfo RPC -method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | height defines at which height to query the historical info. | + + + +### Query +Query defines the gRPC querier service. +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Validators` | [QueryValidatorsRequest](#cosmos.staking.v1beta1.QueryValidatorsRequest) | [QueryValidatorsResponse](#cosmos.staking.v1beta1.QueryValidatorsResponse) | Validators queries all validators that match the given status. | GET|/cosmos/staking/v1beta1/validators| +| `Validator` | [QueryValidatorRequest](#cosmos.staking.v1beta1.QueryValidatorRequest) | [QueryValidatorResponse](#cosmos.staking.v1beta1.QueryValidatorResponse) | Validator queries validator info for given validator address. | GET|/cosmos/staking/v1beta1/validators/{validator_addr}| +| `ValidatorDelegations` | [QueryValidatorDelegationsRequest](#cosmos.staking.v1beta1.QueryValidatorDelegationsRequest) | [QueryValidatorDelegationsResponse](#cosmos.staking.v1beta1.QueryValidatorDelegationsResponse) | ValidatorDelegations queries delegate info for given validator. | GET|/cosmos/staking/v1beta1/validators/{validator_addr}/delegations| +| `ValidatorUnbondingDelegations` | [QueryValidatorUnbondingDelegationsRequest](#cosmos.staking.v1beta1.QueryValidatorUnbondingDelegationsRequest) | [QueryValidatorUnbondingDelegationsResponse](#cosmos.staking.v1beta1.QueryValidatorUnbondingDelegationsResponse) | ValidatorUnbondingDelegations queries unbonding delegations of a validator. | GET|/cosmos/staking/v1beta1/validators/{validator_addr}/unbonding_delegations| +| `Delegation` | [QueryDelegationRequest](#cosmos.staking.v1beta1.QueryDelegationRequest) | [QueryDelegationResponse](#cosmos.staking.v1beta1.QueryDelegationResponse) | Delegation queries delegate info for given validator delegator pair. | GET|/cosmos/staking/v1beta1/validators/{validator_addr}/delegations/{delegator_addr}| +| `UnbondingDelegation` | [QueryUnbondingDelegationRequest](#cosmos.staking.v1beta1.QueryUnbondingDelegationRequest) | [QueryUnbondingDelegationResponse](#cosmos.staking.v1beta1.QueryUnbondingDelegationResponse) | UnbondingDelegation queries unbonding info for given validator delegator pair. | GET|/cosmos/staking/v1beta1/validators/{validator_addr}/delegations/{delegator_addr}/unbonding_delegation| +| `DelegatorDelegations` | [QueryDelegatorDelegationsRequest](#cosmos.staking.v1beta1.QueryDelegatorDelegationsRequest) | [QueryDelegatorDelegationsResponse](#cosmos.staking.v1beta1.QueryDelegatorDelegationsResponse) | DelegatorDelegations queries all delegations of a given delegator address. | GET|/cosmos/staking/v1beta1/delegations/{delegator_addr}| +| `DelegatorUnbondingDelegations` | [QueryDelegatorUnbondingDelegationsRequest](#cosmos.staking.v1beta1.QueryDelegatorUnbondingDelegationsRequest) | [QueryDelegatorUnbondingDelegationsResponse](#cosmos.staking.v1beta1.QueryDelegatorUnbondingDelegationsResponse) | DelegatorUnbondingDelegations queries all unbonding delegations of a given delegator address. | GET|/cosmos/staking/v1beta1/delegators/{delegator_addr}/unbonding_delegations| +| `Redelegations` | [QueryRedelegationsRequest](#cosmos.staking.v1beta1.QueryRedelegationsRequest) | [QueryRedelegationsResponse](#cosmos.staking.v1beta1.QueryRedelegationsResponse) | Redelegations queries redelegations of given address. | GET|/cosmos/staking/v1beta1/delegators/{delegator_addr}/redelegations| +| `DelegatorValidators` | [QueryDelegatorValidatorsRequest](#cosmos.staking.v1beta1.QueryDelegatorValidatorsRequest) | [QueryDelegatorValidatorsResponse](#cosmos.staking.v1beta1.QueryDelegatorValidatorsResponse) | DelegatorValidators queries all validators info for given delegator address. | GET|/cosmos/staking/v1beta1/delegators/{delegator_addr}/validators| +| `DelegatorValidator` | [QueryDelegatorValidatorRequest](#cosmos.staking.v1beta1.QueryDelegatorValidatorRequest) | [QueryDelegatorValidatorResponse](#cosmos.staking.v1beta1.QueryDelegatorValidatorResponse) | DelegatorValidator queries validator info for given delegator validator pair. | GET|/cosmos/staking/v1beta1/delegators/{delegator_addr}/validators/{validator_addr}| +| `HistoricalInfo` | [QueryHistoricalInfoRequest](#cosmos.staking.v1beta1.QueryHistoricalInfoRequest) | [QueryHistoricalInfoResponse](#cosmos.staking.v1beta1.QueryHistoricalInfoResponse) | HistoricalInfo queries the historical info for given height. | GET|/cosmos/staking/v1beta1/historical_info/{height}| +| `Pool` | [QueryPoolRequest](#cosmos.staking.v1beta1.QueryPoolRequest) | [QueryPoolResponse](#cosmos.staking.v1beta1.QueryPoolResponse) | Pool queries the pool info. | GET|/cosmos/staking/v1beta1/pool| +| `Params` | [QueryParamsRequest](#cosmos.staking.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.staking.v1beta1.QueryParamsResponse) | Parameters queries the staking parameters. | GET|/cosmos/staking/v1beta1/params| - + -### QueryHistoricalInfoResponse -QueryHistoricalInfoResponse is response type for the Query/HistoricalInfo RPC -method. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `hist` | [HistoricalInfo](#cosmos.staking.v1beta1.HistoricalInfo) | | hist defines the historical info at the given height. | + +

      Top

      +## cosmos/staking/v1beta1/tx.proto + +### MsgBeginRedelegate +MsgBeginRedelegate defines a SDK message for performing a redelegation +of coins from a delegator and source validator to a destination validator. - -### QueryParamsRequest -QueryParamsRequest is request type for the Query/Params RPC method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | | +| `validator_src_address` | [string](#string) | | | +| `validator_dst_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - + -### QueryParamsResponse -QueryParamsResponse is response type for the Query/Params RPC method. +### MsgBeginRedelegateResponse +MsgBeginRedelegateResponse defines the Msg/BeginRedelegate response type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.staking.v1beta1.Params) | | params holds all the parameters of this module. | +| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - + -### QueryPoolRequest -QueryPoolRequest is request type for the Query/Pool RPC method. +### MsgCreateValidator +MsgCreateValidator defines a SDK message for creating a new validator. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `description` | [Description](#cosmos.staking.v1beta1.Description) | | | +| `commission` | [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) | | | +| `min_self_delegation` | [string](#string) | | | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | +| `pubkey` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `value` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - -### QueryPoolResponse -QueryPoolResponse is response type for the Query/Pool RPC method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `pool` | [Pool](#cosmos.staking.v1beta1.Pool) | | pool defines the pool info. | +### MsgCreateValidatorResponse +MsgCreateValidatorResponse defines the Msg/CreateValidator response type. - + -### QueryRedelegationsRequest -QueryRedelegationsRequest is request type for the Query/Redelegations RPC -method. +### MsgDelegate +MsgDelegate defines a SDK message for performing a delegation of coins +from a delegator to a validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_addr` | [string](#string) | | delegator_addr defines the delegator address to query for. | -| `src_validator_addr` | [string](#string) | | src_validator_addr defines the validator address to redelegate from. | -| `dst_validator_addr` | [string](#string) | | dst_validator_addr defines the validator address to redelegate to. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - - +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - -### QueryRedelegationsResponse -QueryRedelegationsResponse is response type for the Query/Redelegations RPC -method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `redelegation_responses` | [RedelegationResponse](#cosmos.staking.v1beta1.RedelegationResponse) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +### MsgDelegateResponse +MsgDelegateResponse defines the Msg/Delegate response type. - + -### QueryUnbondingDelegationRequest -QueryUnbondingDelegationRequest is request type for the -Query/UnbondingDelegation RPC method. +### MsgEditValidator +MsgEditValidator defines a SDK message for editing an existing validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_addr` | [string](#string) | | delegator_addr defines the delegator address to query for. | -| `validator_addr` | [string](#string) | | validator_addr defines the validator address to query for. | - - +| `description` | [Description](#cosmos.staking.v1beta1.Description) | | | +| `validator_address` | [string](#string) | | | +| `commission_rate` | [string](#string) | | We pass a reference to the new commission rate and min self delegation as it's not mandatory to update. If not updated, the deserialized rate will be zero with no way to distinguish if an update was intended. REF: #2373 | +| `min_self_delegation` | [string](#string) | | | - -### QueryUnbondingDelegationResponse -QueryDelegationResponse is response type for the Query/UnbondingDelegation -RPC method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `unbond` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | | unbond defines the unbonding information of a delegation. | +### MsgEditValidatorResponse +MsgEditValidatorResponse defines the Msg/EditValidator response type. - + -### QueryValidatorDelegationsRequest -QueryValidatorDelegationsRequest is request type for the -Query/ValidatorDelegations RPC method +### MsgUndelegate +MsgUndelegate defines a SDK message for performing an undelegation from a +delegate and a validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_addr` | [string](#string) | | validator_addr defines the validator address to query for. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - + -### QueryValidatorDelegationsResponse -QueryValidatorDelegationsResponse is response type for the -Query/ValidatorDelegations RPC method +### MsgUndelegateResponse +MsgUndelegateResponse defines the Msg/Undelegate response type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegation_responses` | [DelegationResponse](#cosmos.staking.v1beta1.DelegationResponse) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | + - + -### QueryValidatorRequest -QueryValidatorRequest is response type for the Query/Validator RPC method + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_addr` | [string](#string) | | validator_addr defines the validator address to query for. | + + +### Msg +Msg defines the staking Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `CreateValidator` | [MsgCreateValidator](#cosmos.staking.v1beta1.MsgCreateValidator) | [MsgCreateValidatorResponse](#cosmos.staking.v1beta1.MsgCreateValidatorResponse) | CreateValidator defines a method for creating a new validator. | | +| `EditValidator` | [MsgEditValidator](#cosmos.staking.v1beta1.MsgEditValidator) | [MsgEditValidatorResponse](#cosmos.staking.v1beta1.MsgEditValidatorResponse) | EditValidator defines a method for editing an existing validator. | | +| `Delegate` | [MsgDelegate](#cosmos.staking.v1beta1.MsgDelegate) | [MsgDelegateResponse](#cosmos.staking.v1beta1.MsgDelegateResponse) | Delegate defines a method for performing a delegation of coins from a delegator to a validator. | | +| `BeginRedelegate` | [MsgBeginRedelegate](#cosmos.staking.v1beta1.MsgBeginRedelegate) | [MsgBeginRedelegateResponse](#cosmos.staking.v1beta1.MsgBeginRedelegateResponse) | BeginRedelegate defines a method for performing a redelegation of coins from a delegator and source validator to a destination validator. | | +| `Undelegate` | [MsgUndelegate](#cosmos.staking.v1beta1.MsgUndelegate) | [MsgUndelegateResponse](#cosmos.staking.v1beta1.MsgUndelegateResponse) | Undelegate defines a method for performing an undelegation from a delegate and a validator. | | + + +

      Top

      +## cosmos/tx/signing/v1beta1/signing.proto - -### QueryValidatorResponse -QueryValidatorResponse is response type for the Query/Validator RPC method + + + +### SignatureDescriptor +SignatureDescriptor is a convenience type which represents the full data for +a signature including the public key of the signer, signing modes and the +signature itself. It is primarily used for coordinating signatures between +clients. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator` | [Validator](#cosmos.staking.v1beta1.Validator) | | validator defines the the validator info. | +| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public_key is the public key of the signer | +| `data` | [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) | | | +| `sequence` | [uint64](#uint64) | | sequence is the sequence of the account, which describes the number of committed transactions signed by a given address. It is used to prevent replay attacks. | - + -### QueryValidatorUnbondingDelegationsRequest -QueryValidatorUnbondingDelegationsRequest is required type for the -Query/ValidatorUnbondingDelegations RPC method +### SignatureDescriptor.Data +Data represents signature data | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_addr` | [string](#string) | | validator_addr defines the validator address to query for. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +| `single` | [SignatureDescriptor.Data.Single](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Single) | | single represents a single signer | +| `multi` | [SignatureDescriptor.Data.Multi](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Multi) | | multi represents a multisig signer | - + -### QueryValidatorUnbondingDelegationsResponse -QueryValidatorUnbondingDelegationsResponse is response type for the -Query/ValidatorUnbondingDelegations RPC method. +### SignatureDescriptor.Data.Multi +Multi is the signature data for a multisig public key | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `unbonding_responses` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| `bitarray` | [cosmos.crypto.multisig.v1beta1.CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) | | bitarray specifies which keys within the multisig are signing | +| `signatures` | [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) | repeated | signatures is the signatures of the multi-signature | - + -### QueryValidatorsRequest -QueryValidatorsRequest is request type for Query/Validators RPC method. +### SignatureDescriptor.Data.Single +Single is the signature data for a single signer | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `status` | [string](#string) | | status enables to query for validators matching a given status. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +| `mode` | [SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | +| `signature` | [bytes](#bytes) | | signature is the raw signature bytes | - + -### QueryValidatorsResponse -QueryValidatorsResponse is response type for the Query/Validators RPC method +### SignatureDescriptors +SignatureDescriptors wraps multiple SignatureDescriptor's. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validators` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | validators contains all the queried validators. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| `signatures` | [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) | repeated | signatures are the signature descriptors | @@ -6712,260 +6909,208 @@ QueryValidatorsResponse is response type for the Query/Validators RPC method - - + +### SignMode +SignMode represents a signing mode with its own security guarantees. - +| Name | Number | Description | +| ---- | ------ | ----------- | +| SIGN_MODE_UNSPECIFIED | 0 | SIGN_MODE_UNSPECIFIED specifies an unknown signing mode and will be rejected | +| SIGN_MODE_DIRECT | 1 | SIGN_MODE_DIRECT specifies a signing mode which uses SignDoc and is verified with raw bytes from Tx | +| SIGN_MODE_TEXTUAL | 2 | SIGN_MODE_TEXTUAL is a future signing mode that will verify some human-readable textual representation on top of the binary representation from SIGN_MODE_DIRECT | +| SIGN_MODE_LEGACY_AMINO_JSON | 127 | SIGN_MODE_LEGACY_AMINO_JSON is a backwards compatibility mode which uses Amino JSON and will be removed in the future | -### Query -Query defines the gRPC querier service. -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Validators` | [QueryValidatorsRequest](#cosmos.staking.v1beta1.QueryValidatorsRequest) | [QueryValidatorsResponse](#cosmos.staking.v1beta1.QueryValidatorsResponse) | Validators queries all validators that match the given status. | GET|/cosmos/staking/v1beta1/validators| -| `Validator` | [QueryValidatorRequest](#cosmos.staking.v1beta1.QueryValidatorRequest) | [QueryValidatorResponse](#cosmos.staking.v1beta1.QueryValidatorResponse) | Validator queries validator info for given validator address. | GET|/cosmos/staking/v1beta1/validators/{validator_addr}| -| `ValidatorDelegations` | [QueryValidatorDelegationsRequest](#cosmos.staking.v1beta1.QueryValidatorDelegationsRequest) | [QueryValidatorDelegationsResponse](#cosmos.staking.v1beta1.QueryValidatorDelegationsResponse) | ValidatorDelegations queries delegate info for given validator. | GET|/cosmos/staking/v1beta1/validators/{validator_addr}/delegations| -| `ValidatorUnbondingDelegations` | [QueryValidatorUnbondingDelegationsRequest](#cosmos.staking.v1beta1.QueryValidatorUnbondingDelegationsRequest) | [QueryValidatorUnbondingDelegationsResponse](#cosmos.staking.v1beta1.QueryValidatorUnbondingDelegationsResponse) | ValidatorUnbondingDelegations queries unbonding delegations of a validator. | GET|/cosmos/staking/v1beta1/validators/{validator_addr}/unbonding_delegations| -| `Delegation` | [QueryDelegationRequest](#cosmos.staking.v1beta1.QueryDelegationRequest) | [QueryDelegationResponse](#cosmos.staking.v1beta1.QueryDelegationResponse) | Delegation queries delegate info for given validator delegator pair. | GET|/cosmos/staking/v1beta1/validators/{validator_addr}/delegations/{delegator_addr}| -| `UnbondingDelegation` | [QueryUnbondingDelegationRequest](#cosmos.staking.v1beta1.QueryUnbondingDelegationRequest) | [QueryUnbondingDelegationResponse](#cosmos.staking.v1beta1.QueryUnbondingDelegationResponse) | UnbondingDelegation queries unbonding info for given validator delegator pair. | GET|/cosmos/staking/v1beta1/validators/{validator_addr}/delegations/{delegator_addr}/unbonding_delegation| -| `DelegatorDelegations` | [QueryDelegatorDelegationsRequest](#cosmos.staking.v1beta1.QueryDelegatorDelegationsRequest) | [QueryDelegatorDelegationsResponse](#cosmos.staking.v1beta1.QueryDelegatorDelegationsResponse) | DelegatorDelegations queries all delegations of a given delegator address. | GET|/cosmos/staking/v1beta1/delegations/{delegator_addr}| -| `DelegatorUnbondingDelegations` | [QueryDelegatorUnbondingDelegationsRequest](#cosmos.staking.v1beta1.QueryDelegatorUnbondingDelegationsRequest) | [QueryDelegatorUnbondingDelegationsResponse](#cosmos.staking.v1beta1.QueryDelegatorUnbondingDelegationsResponse) | DelegatorUnbondingDelegations queries all unbonding delegations of a given delegator address. | GET|/cosmos/staking/v1beta1/delegators/{delegator_addr}/unbonding_delegations| -| `Redelegations` | [QueryRedelegationsRequest](#cosmos.staking.v1beta1.QueryRedelegationsRequest) | [QueryRedelegationsResponse](#cosmos.staking.v1beta1.QueryRedelegationsResponse) | Redelegations queries redelegations of given address. | GET|/cosmos/staking/v1beta1/delegators/{delegator_addr}/redelegations| -| `DelegatorValidators` | [QueryDelegatorValidatorsRequest](#cosmos.staking.v1beta1.QueryDelegatorValidatorsRequest) | [QueryDelegatorValidatorsResponse](#cosmos.staking.v1beta1.QueryDelegatorValidatorsResponse) | DelegatorValidators queries all validators info for given delegator address. | GET|/cosmos/staking/v1beta1/delegators/{delegator_addr}/validators| -| `DelegatorValidator` | [QueryDelegatorValidatorRequest](#cosmos.staking.v1beta1.QueryDelegatorValidatorRequest) | [QueryDelegatorValidatorResponse](#cosmos.staking.v1beta1.QueryDelegatorValidatorResponse) | DelegatorValidator queries validator info for given delegator validator pair. | GET|/cosmos/staking/v1beta1/delegators/{delegator_addr}/validators/{validator_addr}| -| `HistoricalInfo` | [QueryHistoricalInfoRequest](#cosmos.staking.v1beta1.QueryHistoricalInfoRequest) | [QueryHistoricalInfoResponse](#cosmos.staking.v1beta1.QueryHistoricalInfoResponse) | HistoricalInfo queries the historical info for given height. | GET|/cosmos/staking/v1beta1/historical_info/{height}| -| `Pool` | [QueryPoolRequest](#cosmos.staking.v1beta1.QueryPoolRequest) | [QueryPoolResponse](#cosmos.staking.v1beta1.QueryPoolResponse) | Pool queries the pool info. | GET|/cosmos/staking/v1beta1/pool| -| `Params` | [QueryParamsRequest](#cosmos.staking.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.staking.v1beta1.QueryParamsResponse) | Parameters queries the staking parameters. | GET|/cosmos/staking/v1beta1/params| + + + - +

      Top

      -## cosmos/staking/v1beta1/tx.proto +## cosmos/tx/v1beta1/tx.proto - + -### MsgBeginRedelegate -MsgBeginRedelegate defines a SDK message for performing a redelegation -of coins from a delegator and source validator to a destination validator. +### AuthInfo +AuthInfo describes the fee and signer modes that are used to sign a +transaction. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_src_address` | [string](#string) | | | -| `validator_dst_address` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | +| `signer_infos` | [SignerInfo](#cosmos.tx.v1beta1.SignerInfo) | repeated | signer_infos defines the signing modes for the required signers. The number and order of elements must match the required signers from TxBody's messages. The first element is the primary signer and the one which pays the fee. | +| `fee` | [Fee](#cosmos.tx.v1beta1.Fee) | | Fee is the fee and gas limit for the transaction. The first signer is the primary signer and the one which pays the fee. The fee can be calculated based on the cost of evaluating the body and doing signature verification of the signers. This can be estimated via simulation. | - + -### MsgBeginRedelegateResponse -MsgBeginRedelegateResponse defines the Msg/BeginRedelegate response type. +### Fee +Fee includes the amount of coins paid in fees and the maximum +gas to be used by the transaction. The ratio yields an effective "gasprice", +which must be above some miminum to be accepted into the mempool. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | amount is the amount of coins to be paid as a fee | +| `gas_limit` | [uint64](#uint64) | | gas_limit is the maximum gas that can be used in transaction processing before an out of gas error occurs | +| `payer` | [string](#string) | | if unset, the first signer is responsible for paying the fees. If set, the specified account must pay the fees. the payer must be a tx signer (and thus have signed this field in AuthInfo). setting this field does *not* change the ordering of required signers for the transaction. | +| `granter` | [string](#string) | | if set, the fee payer (either the first signer or the value of the payer field) requests that a fee grant be used to pay fees instead of the fee payer's own balance. If an appropriate fee grant does not exist or the chain does not support fee grants, this will fail | - + -### MsgCreateValidator -MsgCreateValidator defines a SDK message for creating a new validator. +### ModeInfo +ModeInfo describes the signing mode of a single or nested multisig signer. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `description` | [Description](#cosmos.staking.v1beta1.Description) | | | -| `commission` | [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) | | | -| `min_self_delegation` | [string](#string) | | | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | -| `pubkey` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `value` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - - - - - - - - -### MsgCreateValidatorResponse -MsgCreateValidatorResponse defines the Msg/CreateValidator response type. +| `single` | [ModeInfo.Single](#cosmos.tx.v1beta1.ModeInfo.Single) | | single represents a single signer | +| `multi` | [ModeInfo.Multi](#cosmos.tx.v1beta1.ModeInfo.Multi) | | multi represents a nested multisig signer | - + -### MsgDelegate -MsgDelegate defines a SDK message for performing a delegation of coins -from a delegator to a validator. +### ModeInfo.Multi +Multi is the mode info for a multisig public key | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - - - - - - - - -### MsgDelegateResponse -MsgDelegateResponse defines the Msg/Delegate response type. +| `bitarray` | [cosmos.crypto.multisig.v1beta1.CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) | | bitarray specifies which keys within the multisig are signing | +| `mode_infos` | [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) | repeated | mode_infos is the corresponding modes of the signers of the multisig which could include nested multisig public keys | - + -### MsgEditValidator -MsgEditValidator defines a SDK message for editing an existing validator. +### ModeInfo.Single +Single is the mode info for a single signer. It is structured as a message +to allow for additional fields such as locale for SIGN_MODE_TEXTUAL in the +future | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `description` | [Description](#cosmos.staking.v1beta1.Description) | | | -| `validator_address` | [string](#string) | | | -| `commission_rate` | [string](#string) | | We pass a reference to the new commission rate and min self delegation as it's not mandatory to update. If not updated, the deserialized rate will be zero with no way to distinguish if an update was intended. REF: #2373 | -| `min_self_delegation` | [string](#string) | | | - - - - - - - - -### MsgEditValidatorResponse -MsgEditValidatorResponse defines the Msg/EditValidator response type. +| `mode` | [cosmos.tx.signing.v1beta1.SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | - + -### MsgUndelegate -MsgUndelegate defines a SDK message for performing an undelegation from a -delegate and a validator. +### SignDoc +SignDoc is the type used for generating sign bytes for SIGN_MODE_DIRECT. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | +| `body_bytes` | [bytes](#bytes) | | body_bytes is protobuf serialization of a TxBody that matches the representation in TxRaw. | +| `auth_info_bytes` | [bytes](#bytes) | | auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in TxRaw. | +| `chain_id` | [string](#string) | | chain_id is the unique identifier of the chain this transaction targets. It prevents signed transactions from being used on another chain by an attacker | +| `account_number` | [uint64](#uint64) | | account_number is the account number of the account in state | - + -### MsgUndelegateResponse -MsgUndelegateResponse defines the Msg/Undelegate response type. +### SignerInfo +SignerInfo describes the public key and signing mode of a single top-level +signer. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - - - - +| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public_key is the public key of the signer. It is optional for accounts that already exist in state. If unset, the verifier can use the required \ signer address for this position and lookup the public key. | +| `mode_info` | [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) | | mode_info describes the signing mode of the signer and is a nested structure to support nested multisig pubkey's | +| `sequence` | [uint64](#uint64) | | sequence is the sequence of the account, which describes the number of committed transactions signed by a given address. It is used to prevent replay attacks. | - - - - -### Msg -Msg defines the staking Msg service. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `CreateValidator` | [MsgCreateValidator](#cosmos.staking.v1beta1.MsgCreateValidator) | [MsgCreateValidatorResponse](#cosmos.staking.v1beta1.MsgCreateValidatorResponse) | CreateValidator defines a method for creating a new validator. | | -| `EditValidator` | [MsgEditValidator](#cosmos.staking.v1beta1.MsgEditValidator) | [MsgEditValidatorResponse](#cosmos.staking.v1beta1.MsgEditValidatorResponse) | EditValidator defines a method for editing an existing validator. | | -| `Delegate` | [MsgDelegate](#cosmos.staking.v1beta1.MsgDelegate) | [MsgDelegateResponse](#cosmos.staking.v1beta1.MsgDelegateResponse) | Delegate defines a method for performing a delegation of coins from a delegator to a validator. | | -| `BeginRedelegate` | [MsgBeginRedelegate](#cosmos.staking.v1beta1.MsgBeginRedelegate) | [MsgBeginRedelegateResponse](#cosmos.staking.v1beta1.MsgBeginRedelegateResponse) | BeginRedelegate defines a method for performing a redelegation of coins from a delegator and source validator to a destination validator. | | -| `Undelegate` | [MsgUndelegate](#cosmos.staking.v1beta1.MsgUndelegate) | [MsgUndelegateResponse](#cosmos.staking.v1beta1.MsgUndelegateResponse) | Undelegate defines a method for performing an undelegation from a delegate and a validator. | | +### Tx +Tx is the standard type used for broadcasting transactions. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `body` | [TxBody](#cosmos.tx.v1beta1.TxBody) | | body is the processable content of the transaction | +| `auth_info` | [AuthInfo](#cosmos.tx.v1beta1.AuthInfo) | | auth_info is the authorization related content of the transaction, specifically signers, signer modes and fee | +| `signatures` | [bytes](#bytes) | repeated | signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to allow connecting signature meta information like public key and signing mode by position. | - -

      Top

      -## cosmos/staking/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the staking module's genesis state. +### TxBody +TxBody is the body of a transaction that all signers sign over. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.staking.v1beta1.Params) | | params defines all the paramaters of related to deposit. | -| `last_total_power` | [bytes](#bytes) | | last_total_power tracks the total amounts of bonded tokens recorded during the previous end block. | -| `last_validator_powers` | [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) | repeated | last_validator_powers is a special index that provides a historical list of the last-block's bonded validators. | -| `validators` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | delegations defines the validator set at genesis. | -| `delegations` | [Delegation](#cosmos.staking.v1beta1.Delegation) | repeated | delegations defines the delegations active at genesis. | -| `unbonding_delegations` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | repeated | unbonding_delegations defines the unbonding delegations active at genesis. | -| `redelegations` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | repeated | redelegations defines the redelegations active at genesis. | -| `exported` | [bool](#bool) | | | +| `messages` | [google.protobuf.Any](#google.protobuf.Any) | repeated | messages is a list of messages to be executed. The required signers of those messages define the number and order of elements in AuthInfo's signer_infos and Tx's signatures. Each required signer address is added to the list only the first time it occurs. By convention, the first required signer (usually from the first message) is referred to as the primary signer and pays the fee for the whole transaction. | +| `memo` | [string](#string) | | memo is any arbitrary memo to be added to the transaction | +| `timeout_height` | [uint64](#uint64) | | timeout is the block height after which this transaction will not be processed by the chain | +| `extension_options` | [google.protobuf.Any](#google.protobuf.Any) | repeated | extension_options are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, the transaction will be rejected | +| `non_critical_extension_options` | [google.protobuf.Any](#google.protobuf.Any) | repeated | extension_options are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, they will be ignored | - + -### LastValidatorPower -LastValidatorPower required for validator set update logic. +### TxRaw +TxRaw is a variant of Tx that pins the signer's exact binary representation +of body and auth_info. This is used for signing, broadcasting and +verification. The binary `serialize(tx: TxRaw)` is stored in Tendermint and +the hash `sha256(serialize(tx: TxRaw))` becomes the "txhash", commonly used +as the transaction ID. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the address of the validator. | -| `power` | [int64](#int64) | | power defines the power of the validator. | +| `body_bytes` | [bytes](#bytes) | | body_bytes is a protobuf serialization of a TxBody that matches the representation in SignDoc. | +| `auth_info_bytes` | [bytes](#bytes) | | auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in SignDoc. | +| `signatures` | [bytes](#bytes) | repeated | signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to allow connecting signature meta information like public key and signing mode by position. | @@ -6981,375 +7126,344 @@ LastValidatorPower required for validator set update logic. - +

      Top

      -## cosmos/staking/v1beta1/staking.proto +## cosmos/tx/v1beta1/service.proto - + -### Commission -Commission defines commission parameters for a given validator. +### BroadcastTxRequest +BroadcastTxRequest is the request type for the Service.BroadcastTxRequest +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `commission_rates` | [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) | | | -| `update_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `tx_bytes` | [bytes](#bytes) | | tx_bytes is the raw transaction. | +| `mode` | [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) | | | - + -### CommissionRates -CommissionRates defines the initial commission rates to be used for creating -a validator. +### BroadcastTxResponse +BroadcastTxResponse is the response type for the +Service.BroadcastTx method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `rate` | [string](#string) | | | -| `max_rate` | [string](#string) | | | -| `max_change_rate` | [string](#string) | | | +| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | - + -### DVPair -DVPair is struct that just has a delegator-validator pair with no other data. -It is intended to be used as a marshalable pointer. For example, a DVPair can -be used to construct the key to getting an UnbondingDelegation from state. +### GetTxRequest +GetTxRequest is the request type for the Service.GetTx +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | +| `hash` | [string](#string) | | hash is the tx hash to query, encoded as a hex string. | - + -### DVPairs -DVPairs defines an array of DVPair objects. +### GetTxResponse +GetTxResponse is the response type for the Service.GetTx method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pairs` | [DVPair](#cosmos.staking.v1beta1.DVPair) | repeated | | +| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the queried transaction. | +| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | - + -### DVVTriplet -DVVTriplet is struct that just has a delegator-validator-validator triplet -with no other data. It is intended to be used as a marshalable pointer. For -example, a DVVTriplet can be used to construct the key to getting a -Redelegation from state. +### GetTxsEventRequest +GetTxsEventRequest is the request type for the Service.TxsByEvents +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_src_address` | [string](#string) | | | -| `validator_dst_address` | [string](#string) | | | +| `events` | [string](#string) | repeated | events is the list of transaction event type. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - + -### DVVTriplets -DVVTriplets defines an array of DVVTriplet objects. +### GetTxsEventResponse +GetTxsEventResponse is the response type for the Service.TxsByEvents +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `triplets` | [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) | repeated | | +| `txs` | [Tx](#cosmos.tx.v1beta1.Tx) | repeated | txs is the list of queried transactions. | +| `tx_responses` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | tx_responses is the list of queried TxResponses. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | - + -### Delegation -Delegation represents the bond with tokens held by an account. It is -owned by one delegator, and is associated with the voting power of one -validator. +### SimulateRequest +SimulateRequest is the request type for the Service.Simulate +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | -| `shares` | [string](#string) | | | +| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the transaction to simulate. | - + -### DelegationResponse -DelegationResponse is equivalent to Delegation except that it contains a -balance in addition to shares which is more suitable for client responses. +### SimulateResponse +SimulateResponse is the response type for the +Service.SimulateRPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegation` | [Delegation](#cosmos.staking.v1beta1.Delegation) | | | -| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | +| `gas_info` | [cosmos.base.abci.v1beta1.GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | gas_info is the information about gas used in the simulation. | +| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | result is the result of the simulation. | + - -### Description -Description defines a validator description. + +### BroadcastMode +BroadcastMode specifies the broadcast mode for the TxService.Broadcast RPC method. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `moniker` | [string](#string) | | | -| `identity` | [string](#string) | | | -| `website` | [string](#string) | | | -| `security_contact` | [string](#string) | | | -| `details` | [string](#string) | | | +| Name | Number | Description | +| ---- | ------ | ----------- | +| BROADCAST_MODE_UNSPECIFIED | 0 | zero-value for mode ordering | +| BROADCAST_MODE_BLOCK | 1 | BROADCAST_MODE_BLOCK defines a tx broadcasting mode where the client waits for the tx to be committed in a block. | +| BROADCAST_MODE_SYNC | 2 | BROADCAST_MODE_SYNC defines a tx broadcasting mode where the client waits for a CheckTx execution response only. | +| BROADCAST_MODE_ASYNC | 3 | BROADCAST_MODE_ASYNC defines a tx broadcasting mode where the client returns immediately. | + + + - +### Service +Service defines a gRPC service for interacting with transactions. -### HistoricalInfo -HistoricalInfo contains header and validator information for a given block. -It is stored as part of staking module's state, which persists the `n` most -recent HistoricalInfo -(`n` is set by the staking module's `historical_entries` parameter). +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Simulate` | [SimulateRequest](#cosmos.tx.v1beta1.SimulateRequest) | [SimulateResponse](#cosmos.tx.v1beta1.SimulateResponse) | Simulate simulates executing a transaction for estimating gas usage. | POST|/cosmos/tx/v1beta1/simulate| +| `GetTx` | [GetTxRequest](#cosmos.tx.v1beta1.GetTxRequest) | [GetTxResponse](#cosmos.tx.v1beta1.GetTxResponse) | GetTx fetches a tx by hash. | GET|/cosmos/tx/v1beta1/txs/{hash}| +| `BroadcastTx` | [BroadcastTxRequest](#cosmos.tx.v1beta1.BroadcastTxRequest) | [BroadcastTxResponse](#cosmos.tx.v1beta1.BroadcastTxResponse) | BroadcastTx broadcast transaction. | POST|/cosmos/tx/v1beta1/txs| +| `GetTxsEvent` | [GetTxsEventRequest](#cosmos.tx.v1beta1.GetTxsEventRequest) | [GetTxsEventResponse](#cosmos.tx.v1beta1.GetTxsEventResponse) | GetTxsEvent fetches txs by event. | GET|/cosmos/tx/v1beta1/txs| + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `header` | [tendermint.types.Header](#tendermint.types.Header) | | | -| `valset` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | | + +

      Top

      +## cosmos/upgrade/v1beta1/upgrade.proto - + -### Params -Params defines the parameters for the staking module. +### CancelSoftwareUpgradeProposal +CancelSoftwareUpgradeProposal is a gov Content type for cancelling a software +upgrade. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `unbonding_time` | [google.protobuf.Duration](#google.protobuf.Duration) | | | -| `max_validators` | [uint32](#uint32) | | | -| `max_entries` | [uint32](#uint32) | | | -| `historical_entries` | [uint32](#uint32) | | | -| `bond_denom` | [string](#string) | | | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | - + -### Pool -Pool is used for tracking bonded and not-bonded token supply of the bond -denomination. +### Plan +Plan specifies information about a planned upgrade and when it should occur. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `not_bonded_tokens` | [string](#string) | | | -| `bonded_tokens` | [string](#string) | | | +| `name` | [string](#string) | | Sets the name for the upgrade. This name will be used by the upgraded version of the software to apply any special "on-upgrade" commands during the first BeginBlock method after the upgrade is applied. It is also used to detect whether a software version can handle a given upgrade. If no upgrade handler with this name has been set in the software, it will be assumed that the software is out-of-date when the upgrade Time or Height is reached and the software will exit. | +| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | The time after which the upgrade must be performed. Leave set to its zero value to use a pre-defined Height instead. | +| `height` | [int64](#int64) | | The height at which the upgrade must be performed. Only used if Time is not set. | +| `info` | [string](#string) | | Any application specific upgrade info to be included on-chain such as a git commit that validators could automatically upgrade to | +| `upgraded_client_state` | [google.protobuf.Any](#google.protobuf.Any) | | IBC-enabled chains can opt-in to including the upgraded client state in its upgrade plan This will make the chain commit to the correct upgraded (self) client state before the upgrade occurs, so that connecting chains can verify that the new upgraded client is valid by verifying a proof on the previous version of the chain. This will allow IBC connections to persist smoothly across planned chain upgrades | - + -### Redelegation -Redelegation contains the list of a particular delegator's redelegating bonds -from a particular source validator to a particular destination validator. +### SoftwareUpgradeProposal +SoftwareUpgradeProposal is a gov Content type for initiating a software +upgrade. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_src_address` | [string](#string) | | | -| `validator_dst_address` | [string](#string) | | | -| `entries` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | repeated | redelegation entries | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | | + - + -### RedelegationEntry -RedelegationEntry defines a redelegation object with relevant metadata. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `creation_height` | [int64](#int64) | | | -| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `initial_balance` | [string](#string) | | | -| `shares_dst` | [string](#string) | | | + +

      Top

      +## cosmos/upgrade/v1beta1/query.proto - + -### RedelegationEntryResponse -RedelegationEntryResponse is equivalent to a RedelegationEntry except that it -contains a balance in addition to shares which is more suitable for client -responses. +### QueryAppliedPlanRequest +QueryCurrentPlanRequest is the request type for the Query/AppliedPlan RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `redelegation_entry` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | | | -| `balance` | [string](#string) | | | +| `name` | [string](#string) | | name is the name of the applied plan to query for. | - + -### RedelegationResponse -RedelegationResponse is equivalent to a Redelegation except that its entries -contain a balance in addition to shares which is more suitable for client -responses. +### QueryAppliedPlanResponse +QueryAppliedPlanResponse is the response type for the Query/AppliedPlan RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `redelegation` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | | | -| `entries` | [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) | repeated | | - - +| `height` | [int64](#int64) | | height is the block height at which the plan was applied. | - -### UnbondingDelegation -UnbondingDelegation stores all of a single delegator's unbonding bonds -for a single validator in an time-ordered list. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | -| `entries` | [UnbondingDelegationEntry](#cosmos.staking.v1beta1.UnbondingDelegationEntry) | repeated | unbonding delegation entries | +### QueryCurrentPlanRequest +QueryCurrentPlanRequest is the request type for the Query/CurrentPlan RPC +method. - + -### UnbondingDelegationEntry -UnbondingDelegationEntry defines an unbonding object with relevant metadata. +### QueryCurrentPlanResponse +QueryCurrentPlanResponse is the response type for the Query/CurrentPlan RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `creation_height` | [int64](#int64) | | | -| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `initial_balance` | [string](#string) | | | -| `balance` | [string](#string) | | | +| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | plan is the current upgrade plan. | - + -### ValAddresses -ValAddresses defines a repeated set of validator addresses. +### QueryUpgradedConsensusStateRequest +QueryUpgradedConsensusStateRequest is the request type for the Query/UpgradedConsensusState +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `addresses` | [string](#string) | repeated | | +| `last_height` | [int64](#int64) | | last height of the current chain must be sent in request as this is the height under which next consensus state is stored | - + -### Validator -Validator defines a validator, together with the total amount of the -Validator's bond shares and their exchange rate to coins. Slashing results in -a decrease in the exchange rate, allowing correct calculation of future -undelegations without iterating over delegators. When coins are delegated to -this validator, the validator is credited with a delegation whose number of -bond shares is based on the amount of coins delegated divided by the current -exchange rate. Voting power can be calculated as total bonded shares -multiplied by exchange rate. +### QueryUpgradedConsensusStateResponse +QueryUpgradedConsensusStateResponse is the response type for the Query/UpgradedConsensusState +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `operator_address` | [string](#string) | | | -| `consensus_pubkey` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `jailed` | [bool](#bool) | | | -| `status` | [BondStatus](#cosmos.staking.v1beta1.BondStatus) | | | -| `tokens` | [string](#string) | | | -| `delegator_shares` | [string](#string) | | | -| `description` | [Description](#cosmos.staking.v1beta1.Description) | | | -| `unbonding_height` | [int64](#int64) | | | -| `unbonding_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `commission` | [Commission](#cosmos.staking.v1beta1.Commission) | | | -| `min_self_delegation` | [string](#string) | | | +| `upgraded_consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | @@ -7357,23 +7471,21 @@ multiplied by exchange rate. + - - -### BondStatus -BondStatus is the status of a validator. + -| Name | Number | Description | -| ---- | ------ | ----------- | -| BOND_STATUS_UNSPECIFIED | 0 | UNSPECIFIED defines an invalid validator status. | -| BOND_STATUS_UNBONDED | 1 | UNBONDED defines a validator that is not bonded. | -| BOND_STATUS_UNBONDING | 2 | UNBONDING defines a validator that is unbonding. | -| BOND_STATUS_BONDED | 3 | BONDED defines a validator that is bonded. | + - +### Query +Query defines the gRPC upgrade querier service. - +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `CurrentPlan` | [QueryCurrentPlanRequest](#cosmos.upgrade.v1beta1.QueryCurrentPlanRequest) | [QueryCurrentPlanResponse](#cosmos.upgrade.v1beta1.QueryCurrentPlanResponse) | CurrentPlan queries the current upgrade plan. | GET|/cosmos/upgrade/v1beta1/current_plan| +| `AppliedPlan` | [QueryAppliedPlanRequest](#cosmos.upgrade.v1beta1.QueryAppliedPlanRequest) | [QueryAppliedPlanResponse](#cosmos.upgrade.v1beta1.QueryAppliedPlanResponse) | AppliedPlan queries a previously applied upgrade plan by its name. | GET|/cosmos/upgrade/v1beta1/applied_plan/{name}| +| `UpgradedConsensusState` | [QueryUpgradedConsensusStateRequest](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateRequest) | [QueryUpgradedConsensusStateResponse](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse) | UpgradedConsensusState queries the consensus state that will serve as a trusted kernel for the next version of this chain. It will only be stored at the last height of this chain. UpgradedConsensusState RPC not supported with legacy querier | GET|/cosmos/upgrade/v1beta1/upgraded_consensus_state/{last_height}| @@ -7539,99 +7651,96 @@ periodically vests by unlocking coins during each specified period. - +

      Top

      -## cosmos/params/v1beta1/query.proto +## ibc/applications/transfer/v1/transfer.proto - + -### QueryParamsRequest -QueryParamsRequest is request type for the Query/Params RPC method. +### DenomTrace +DenomTrace contains the base denomination for ICS20 fungible tokens and the +source tracing information path. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `subspace` | [string](#string) | | subspace defines the module to query the parameter for. | -| `key` | [string](#string) | | key defines the key of the parameter in the subspace. | +| `path` | [string](#string) | | path defines the chain of port/channel identifiers used for tracing the source of the fungible token. | +| `base_denom` | [string](#string) | | base denomination of the relayed fungible token. | - + -### QueryParamsResponse -QueryParamsResponse is response type for the Query/Params RPC method. +### FungibleTokenPacketData +FungibleTokenPacketData defines a struct for the packet payload +See FungibleTokenPacketData spec: +https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `param` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | | param defines the queried parameter. | - - - - +| `denom` | [string](#string) | | the token denomination to be transferred | +| `amount` | [uint64](#uint64) | | the token amount to be transferred | +| `sender` | [string](#string) | | the sender address | +| `receiver` | [string](#string) | | the recipient address on the destination chain | - - - - -### Query -Query defines the gRPC querier service. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Params` | [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) | Params queries a specific parameter of a module, given its subspace and key. | GET|/cosmos/params/v1beta1/params| +### Params +Params defines the set of IBC transfer parameters. +NOTE: To prevent a single token from being transferred, set the +TransfersEnabled parameter to true and then set the bank module's SendEnabled +parameter for the denomination to false. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `send_enabled` | [bool](#bool) | | send_enabled enables or disables all cross-chain token transfers from this chain. | +| `receive_enabled` | [bool](#bool) | | receive_enabled enables or disables all cross-chain token transfers to this chain. | - -

      Top

      -## cosmos/params/v1beta1/params.proto + - + -### ParamChange -ParamChange defines an individual parameter change, for use in -ParameterChangeProposal. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `subspace` | [string](#string) | | | -| `key` | [string](#string) | | | -| `value` | [string](#string) | | | + +

      Top

      +## ibc/applications/transfer/v1/genesis.proto - + -### ParameterChangeProposal -ParameterChangeProposal defines a proposal to change one or more parameters. +### GenesisState +GenesisState defines the ibc-transfer genesis state | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `changes` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | repeated | | +| `port_id` | [string](#string) | | | +| `denom_traces` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | repeated | | +| `params` | [Params](#ibc.applications.transfer.v1.Params) | | | @@ -7750,180 +7859,16 @@ QueryParamsResponse is the response type for the Query/Params RPC method. - - -### Query -Query provides defines the gRPC querier service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `DenomTrace` | [QueryDenomTraceRequest](#ibc.applications.transfer.v1.QueryDenomTraceRequest) | [QueryDenomTraceResponse](#ibc.applications.transfer.v1.QueryDenomTraceResponse) | DenomTrace queries a denomination trace information. | GET|/ibc/applications/transfer/v1beta1/denom_traces/{hash}| -| `DenomTraces` | [QueryDenomTracesRequest](#ibc.applications.transfer.v1.QueryDenomTracesRequest) | [QueryDenomTracesResponse](#ibc.applications.transfer.v1.QueryDenomTracesResponse) | DenomTraces queries all denomination traces. | GET|/ibc/applications/transfer/v1beta1/denom_traces| -| `Params` | [QueryParamsRequest](#ibc.applications.transfer.v1.QueryParamsRequest) | [QueryParamsResponse](#ibc.applications.transfer.v1.QueryParamsResponse) | Params queries all parameters of the ibc-transfer module. | GET|/ibc/applications/transfer/v1beta1/params| - - - - - - -

      Top

      - -## ibc/applications/transfer/v1/tx.proto - - - - - -### MsgTransfer -MsgTransfer defines a msg to transfer fungible tokens (i.e Coins) between -ICS20 enabled chains. See ICS Spec here: -https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `source_port` | [string](#string) | | the port on which the packet will be sent | -| `source_channel` | [string](#string) | | the channel by which the packet will be sent | -| `token` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | the tokens to be transferred | -| `sender` | [string](#string) | | the sender address | -| `receiver` | [string](#string) | | the recipient address on the destination chain | -| `timeout_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Timeout height relative to the current block height. The timeout is disabled when set to 0. | -| `timeout_timestamp` | [uint64](#uint64) | | Timeout timestamp (in nanoseconds) relative to the current block timestamp. The timeout is disabled when set to 0. | - - - - - - - - -### MsgTransferResponse -MsgTransferResponse defines the Msg/Transfer response type. - - - - - - - - - - - - - - -### Msg -Msg defines the ibc/transfer Msg service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Transfer` | [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) | [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) | Transfer defines a rpc handler method for MsgTransfer. | | - - - - - - -

      Top

      - -## ibc/applications/transfer/v1/transfer.proto - - - - - -### DenomTrace -DenomTrace contains the base denomination for ICS20 fungible tokens and the -source tracing information path. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `path` | [string](#string) | | path defines the chain of port/channel identifiers used for tracing the source of the fungible token. | -| `base_denom` | [string](#string) | | base denomination of the relayed fungible token. | - - - - - - - - -### FungibleTokenPacketData -FungibleTokenPacketData defines a struct for the packet payload -See FungibleTokenPacketData spec: -https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | the token denomination to be transferred | -| `amount` | [uint64](#uint64) | | the token amount to be transferred | -| `sender` | [string](#string) | | the sender address | -| `receiver` | [string](#string) | | the recipient address on the destination chain | - - - - - - - - -### Params -Params defines the set of IBC transfer parameters. -NOTE: To prevent a single token from being transferred, set the -TransfersEnabled parameter to true and then set the bank module's SendEnabled -parameter for the denomination to false. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `send_enabled` | [bool](#bool) | | send_enabled enables or disables all cross-chain token transfers from this chain. | -| `receive_enabled` | [bool](#bool) | | receive_enabled enables or disables all cross-chain token transfers to this chain. | - - - - - - - - - - - - - - - - -

      Top

      - -## ibc/applications/transfer/v1/genesis.proto - - - - - -### GenesisState -GenesisState defines the ibc-transfer genesis state - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `denom_traces` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | repeated | | -| `params` | [Params](#ibc.applications.transfer.v1.Params) | | | - - - - - - + - +### Query +Query provides defines the gRPC querier service. - +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `DenomTrace` | [QueryDenomTraceRequest](#ibc.applications.transfer.v1.QueryDenomTraceRequest) | [QueryDenomTraceResponse](#ibc.applications.transfer.v1.QueryDenomTraceResponse) | DenomTrace queries a denomination trace information. | GET|/ibc/applications/transfer/v1beta1/denom_traces/{hash}| +| `DenomTraces` | [QueryDenomTracesRequest](#ibc.applications.transfer.v1.QueryDenomTracesRequest) | [QueryDenomTracesResponse](#ibc.applications.transfer.v1.QueryDenomTracesResponse) | DenomTraces queries all denomination traces. | GET|/ibc/applications/transfer/v1beta1/denom_traces| +| `Params` | [QueryParamsRequest](#ibc.applications.transfer.v1.QueryParamsRequest) | [QueryParamsResponse](#ibc.applications.transfer.v1.QueryParamsResponse) | Params queries all parameters of the ibc-transfer module. | GET|/ibc/applications/transfer/v1beta1/params| @@ -8054,615 +7999,682 @@ Params defines the set of IBC light client parameters. - +

      Top

      -## ibc/core/client/v1/query.proto +## ibc/applications/transfer/v1/tx.proto - + -### QueryClientParamsRequest -QueryClientParamsRequest is the request type for the Query/ClientParams RPC method. +### MsgTransfer +MsgTransfer defines a msg to transfer fungible tokens (i.e Coins) between +ICS20 enabled chains. See ICS Spec here: +https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `source_port` | [string](#string) | | the port on which the packet will be sent | +| `source_channel` | [string](#string) | | the channel by which the packet will be sent | +| `token` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | the tokens to be transferred | +| `sender` | [string](#string) | | the sender address | +| `receiver` | [string](#string) | | the recipient address on the destination chain | +| `timeout_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Timeout height relative to the current block height. The timeout is disabled when set to 0. | +| `timeout_timestamp` | [uint64](#uint64) | | Timeout timestamp (in nanoseconds) relative to the current block timestamp. The timeout is disabled when set to 0. | - -### QueryClientParamsResponse -QueryClientParamsResponse is the response type for the Query/ClientParams RPC method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params` | [Params](#ibc.core.client.v1.Params) | | params defines the parameters of the module. | +### MsgTransferResponse +MsgTransferResponse defines the Msg/Transfer response type. + - + -### QueryClientStateRequest -QueryClientStateRequest is the request type for the Query/ClientState RPC -method + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client state unique identifier | + +### Msg +Msg defines the ibc/transfer Msg service. +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Transfer` | [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) | [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) | Transfer defines a rpc handler method for MsgTransfer. | | + - + +

      Top

      -### QueryClientStateResponse -QueryClientStateResponse is the response type for the Query/ClientState RPC -method. Besides the client state, it includes a proof and the height from -which the proof was retrieved. +## ibc/core/channel/v1/channel.proto + + + + + +### Acknowledgement +Acknowledgement is the recommended acknowledgement format to be used by +app-specific protocols. +NOTE: The field numbers 21 and 22 were explicitly chosen to avoid accidental +conflicts with other protobuf message formats used for acknowledgements. +The first byte of any message with this format will be the non-ASCII values +`0xaa` (result) or `0xb2` (error). Implemented as defined by ICS: +https://github.com/cosmos/ics/tree/master/spec/ics-004-channel-and-packet-semantics#acknowledgement-envelope | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | client state associated with the request identifier | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | +| `result` | [bytes](#bytes) | | | +| `error` | [string](#string) | | | - + -### QueryClientStatesRequest -QueryClientStatesRequest is the request type for the Query/ClientStates RPC -method +### Channel +Channel defines pipeline for exactly-once packet delivery between specific +modules on separate blockchains, which has at least one end capable of +sending packets and one end capable of receiving packets. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | +| `state` | [State](#ibc.core.channel.v1.State) | | current state of the channel end | +| `ordering` | [Order](#ibc.core.channel.v1.Order) | | whether the channel is ordered or unordered | +| `counterparty` | [Counterparty](#ibc.core.channel.v1.Counterparty) | | counterparty channel end | +| `connection_hops` | [string](#string) | repeated | list of connection identifiers, in order, along which packets sent on this channel will travel | +| `version` | [string](#string) | | opaque channel version, which is agreed upon during the handshake | - + -### QueryClientStatesResponse -QueryClientStatesResponse is the response type for the Query/ClientStates RPC -method. +### Counterparty +Counterparty defines a channel end counterparty | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_states` | [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | repeated | list of stored ClientStates of the chain. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | +| `port_id` | [string](#string) | | port on the counterparty chain which owns the other end of the channel. | +| `channel_id` | [string](#string) | | channel end on the counterparty chain | - + -### QueryConsensusStateRequest -QueryConsensusStateRequest is the request type for the Query/ConsensusState -RPC method. Besides the consensus state, it includes a proof and the height -from which the proof was retrieved. +### IdentifiedChannel +IdentifiedChannel defines a channel with additional port and channel +identifier fields. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier | -| `revision_number` | [uint64](#uint64) | | consensus state revision number | -| `revision_height` | [uint64](#uint64) | | consensus state revision height | -| `latest_height` | [bool](#bool) | | latest_height overrrides the height field and queries the latest stored ConsensusState | +| `state` | [State](#ibc.core.channel.v1.State) | | current state of the channel end | +| `ordering` | [Order](#ibc.core.channel.v1.Order) | | whether the channel is ordered or unordered | +| `counterparty` | [Counterparty](#ibc.core.channel.v1.Counterparty) | | counterparty channel end | +| `connection_hops` | [string](#string) | repeated | list of connection identifiers, in order, along which packets sent on this channel will travel | +| `version` | [string](#string) | | opaque channel version, which is agreed upon during the handshake | +| `port_id` | [string](#string) | | port identifier | +| `channel_id` | [string](#string) | | channel identifier | - + -### QueryConsensusStateResponse -QueryConsensusStateResponse is the response type for the Query/ConsensusState -RPC method +### Packet +Packet defines a type that carries data across different chains through IBC | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the client identifier at the given height | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | +| `sequence` | [uint64](#uint64) | | number corresponds to the order of sends and receives, where a Packet with an earlier sequence number must be sent and received before a Packet with a later sequence number. | +| `source_port` | [string](#string) | | identifies the port on the sending chain. | +| `source_channel` | [string](#string) | | identifies the channel end on the sending chain. | +| `destination_port` | [string](#string) | | identifies the port on the receiving chain. | +| `destination_channel` | [string](#string) | | identifies the channel end on the receiving chain. | +| `data` | [bytes](#bytes) | | actual opaque bytes transferred directly to the application module | +| `timeout_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | block height after which the packet times out | +| `timeout_timestamp` | [uint64](#uint64) | | block timestamp (in nanoseconds) after which the packet times out | - + -### QueryConsensusStatesRequest -QueryConsensusStatesRequest is the request type for the Query/ConsensusStates -RPC method. +### PacketState +PacketState defines the generic type necessary to retrieve and store +packet commitments, acknowledgements, and receipts. +Caller is responsible for knowing the context necessary to interpret this +state as a commitment, acknowledgement, or a receipt. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | +| `port_id` | [string](#string) | | channel port identifier. | +| `channel_id` | [string](#string) | | channel unique identifier. | +| `sequence` | [uint64](#uint64) | | packet sequence. | +| `data` | [bytes](#bytes) | | embedded data that represents packet state. | + - -### QueryConsensusStatesResponse -QueryConsensusStatesResponse is the response type for the -Query/ConsensusStates RPC method + +### Order +Order defines if a channel is ORDERED or UNORDERED -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `consensus_states` | [ConsensusStateWithHeight](#ibc.core.client.v1.ConsensusStateWithHeight) | repeated | consensus states associated with the identifier | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | +| Name | Number | Description | +| ---- | ------ | ----------- | +| ORDER_NONE_UNSPECIFIED | 0 | zero-value for channel ordering | +| ORDER_UNORDERED | 1 | packets can be delivered in any order, which may differ from the order in which they were sent. | +| ORDER_ORDERED | 2 | packets are delivered exactly in the order which they were sent | + +### State +State defines if a channel is in one of the following states: +CLOSED, INIT, TRYOPEN, OPEN or UNINITIALIZED. + +| Name | Number | Description | +| ---- | ------ | ----------- | +| STATE_UNINITIALIZED_UNSPECIFIED | 0 | Default State | +| STATE_INIT | 1 | A channel has just started the opening handshake. | +| STATE_TRYOPEN | 2 | A channel has acknowledged the handshake step on the counterparty chain. | +| STATE_OPEN | 3 | A channel has completed the handshake. Open channels are ready to send and receive packets. | +| STATE_CLOSED | 4 | A channel has been closed and can no longer be used to send or receive packets. | - + - -### Query -Query provides defines the gRPC querier service -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `ClientState` | [QueryClientStateRequest](#ibc.core.client.v1.QueryClientStateRequest) | [QueryClientStateResponse](#ibc.core.client.v1.QueryClientStateResponse) | ClientState queries an IBC light client. | GET|/ibc/core/client/v1beta1/client_states/{client_id}| -| `ClientStates` | [QueryClientStatesRequest](#ibc.core.client.v1.QueryClientStatesRequest) | [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse) | ClientStates queries all the IBC light clients of a chain. | GET|/ibc/core/client/v1beta1/client_states| -| `ConsensusState` | [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest) | [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) | ConsensusState queries a consensus state associated with a client state at a given height. | GET|/ibc/core/client/v1beta1/consensus_states/{client_id}/revision/{revision_number}/height/{revision_height}| -| `ConsensusStates` | [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) | [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) | ConsensusStates queries all the consensus state associated with a given client. | GET|/ibc/core/client/v1beta1/consensus_states/{client_id}| -| `ClientParams` | [QueryClientParamsRequest](#ibc.core.client.v1.QueryClientParamsRequest) | [QueryClientParamsResponse](#ibc.core.client.v1.QueryClientParamsResponse) | ClientParams queries all parameters of the ibc client. | GET|/ibc/client/v1beta1/params| + +

      Top

      - +## ibc/core/channel/v1/genesis.proto - -

      Top

      + -## ibc/core/client/v1/tx.proto +### GenesisState +GenesisState defines the ibc channel submodule's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `channels` | [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) | repeated | | +| `acknowledgements` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | +| `commitments` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | +| `receipts` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | +| `send_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | +| `recv_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | +| `ack_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | +| `next_channel_sequence` | [uint64](#uint64) | | the sequence for the next generated channel identifier | - -### MsgCreateClient -MsgCreateClient defines a message to create an IBC client -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | light client state | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the client that corresponds to a given height. | -| `signer` | [string](#string) | | signer address | + + +### PacketSequence +PacketSequence defines the genesis type necessary to retrieve and store +next send and receive sequences. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `port_id` | [string](#string) | | | +| `channel_id` | [string](#string) | | | +| `sequence` | [uint64](#uint64) | | | + + + + + + + + + + + + + + + + +

      Top

      +## ibc/core/channel/v1/query.proto + +### QueryChannelClientStateRequest +QueryChannelClientStateRequest is the request type for the Query/ClientState +RPC method - -### MsgCreateClientResponse -MsgCreateClientResponse defines the Msg/CreateClient response type. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | - + -### MsgSubmitMisbehaviour -MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for -light client misbehaviour. +### QueryChannelClientStateResponse +QueryChannelClientStateResponse is the Response type for the +Query/QueryChannelClientState RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client unique identifier | -| `misbehaviour` | [google.protobuf.Any](#google.protobuf.Any) | | misbehaviour used for freezing the light client | -| `signer` | [string](#string) | | signer address | +| `identified_client_state` | [ibc.core.client.v1.IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | | client state associated with the channel | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - + -### MsgSubmitMisbehaviourResponse -MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response type. +### QueryChannelConsensusStateRequest +QueryChannelConsensusStateRequest is the request type for the +Query/ConsensusState RPC method +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `revision_number` | [uint64](#uint64) | | revision number of the consensus state | +| `revision_height` | [uint64](#uint64) | | revision height of the consensus state | - -### MsgUpdateClient -MsgUpdateClient defines an sdk.Msg to update a IBC client state using -the given header. + + + +### QueryChannelConsensusStateResponse +QueryChannelClientStateResponse is the Response type for the +Query/QueryChannelClientState RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client unique identifier | -| `header` | [google.protobuf.Any](#google.protobuf.Any) | | header to update the light client | -| `signer` | [string](#string) | | signer address | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the channel | +| `client_id` | [string](#string) | | client ID associated with the consensus state | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - + -### MsgUpdateClientResponse -MsgUpdateClientResponse defines the Msg/UpdateClient response type. +### QueryChannelRequest +QueryChannelRequest is the request type for the Query/Channel RPC method +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | - -### MsgUpgradeClient -MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client unique identifier | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | upgraded client state | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | upgraded consensus state, only contains enough information to serve as a basis of trust in update logic | -| `proof_upgrade_client` | [bytes](#bytes) | | proof that old chain committed to new client | -| `proof_upgrade_consensus_state` | [bytes](#bytes) | | proof that old chain committed to new consensus state | -| `signer` | [string](#string) | | signer address | +### QueryChannelResponse +QueryChannelResponse is the response type for the Query/Channel RPC method. +Besides the Channel end, it includes a proof and the height from which the +proof was retrieved. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `channel` | [Channel](#ibc.core.channel.v1.Channel) | | channel associated with the request identifiers | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - -### MsgUpgradeClientResponse -MsgUpgradeClientResponse defines the Msg/UpgradeClient response type. + +### QueryChannelsRequest +QueryChannelsRequest is the request type for the Query/Channels RPC method +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - - - - -### Msg -Msg defines the ibc/client Msg service. + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `CreateClient` | [MsgCreateClient](#ibc.core.client.v1.MsgCreateClient) | [MsgCreateClientResponse](#ibc.core.client.v1.MsgCreateClientResponse) | CreateClient defines a rpc handler method for MsgCreateClient. | | -| `UpdateClient` | [MsgUpdateClient](#ibc.core.client.v1.MsgUpdateClient) | [MsgUpdateClientResponse](#ibc.core.client.v1.MsgUpdateClientResponse) | UpdateClient defines a rpc handler method for MsgUpdateClient. | | -| `UpgradeClient` | [MsgUpgradeClient](#ibc.core.client.v1.MsgUpgradeClient) | [MsgUpgradeClientResponse](#ibc.core.client.v1.MsgUpgradeClientResponse) | UpgradeClient defines a rpc handler method for MsgUpgradeClient. | | -| `SubmitMisbehaviour` | [MsgSubmitMisbehaviour](#ibc.core.client.v1.MsgSubmitMisbehaviour) | [MsgSubmitMisbehaviourResponse](#ibc.core.client.v1.MsgSubmitMisbehaviourResponse) | SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour. | | +### QueryChannelsResponse +QueryChannelsResponse is the response type for the Query/Channels RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `channels` | [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) | repeated | list of stored channels of the chain. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | - -

      Top

      -## ibc/core/client/v1/genesis.proto - + -### GenesisMetadata -GenesisMetadata defines the genesis type for metadata that clients may return -with ExportMetadata +### QueryConnectionChannelsRequest +QueryConnectionChannelsRequest is the request type for the +Query/QueryConnectionChannels RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | store key of metadata without clientID-prefix | -| `value` | [bytes](#bytes) | | metadata value | +| `connection` | [string](#string) | | connection unique identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - + -### GenesisState -GenesisState defines the ibc client submodule's genesis state. +### QueryConnectionChannelsResponse +QueryConnectionChannelsResponse is the Response type for the +Query/QueryConnectionChannels RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `clients` | [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | repeated | client states with their corresponding identifiers | -| `clients_consensus` | [ClientConsensusStates](#ibc.core.client.v1.ClientConsensusStates) | repeated | consensus states from each client | -| `clients_metadata` | [IdentifiedGenesisMetadata](#ibc.core.client.v1.IdentifiedGenesisMetadata) | repeated | metadata from each client | -| `params` | [Params](#ibc.core.client.v1.Params) | | | -| `create_localhost` | [bool](#bool) | | create localhost on initialization | -| `next_client_sequence` | [uint64](#uint64) | | the sequence for the next generated client identifier | +| `channels` | [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) | repeated | list of channels associated with a connection. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | - + -### IdentifiedGenesisMetadata -IdentifiedGenesisMetadata has the client metadata with the corresponding client id. +### QueryNextSequenceReceiveRequest +QueryNextSequenceReceiveRequest is the request type for the +Query/QueryNextSequenceReceiveRequest RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `client_metadata` | [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) | repeated | | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | - - + - +### QueryNextSequenceReceiveResponse +QuerySequenceResponse is the request type for the +Query/QueryNextSequenceReceiveResponse RPC method - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `next_sequence_receive` | [uint64](#uint64) | | next sequence receive number | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - -

      Top

      -## ibc/core/channel/v1/channel.proto - + -### Acknowledgement -Acknowledgement is the recommended acknowledgement format to be used by -app-specific protocols. -NOTE: The field numbers 21 and 22 were explicitly chosen to avoid accidental -conflicts with other protobuf message formats used for acknowledgements. -The first byte of any message with this format will be the non-ASCII values -`0xaa` (result) or `0xb2` (error). Implemented as defined by ICS: -https://github.com/cosmos/ics/tree/master/spec/ics-004-channel-and-packet-semantics#acknowledgement-envelope +### QueryPacketAcknowledgementRequest +QueryPacketAcknowledgementRequest is the request type for the +Query/PacketAcknowledgement RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `result` | [bytes](#bytes) | | | -| `error` | [string](#string) | | | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `sequence` | [uint64](#uint64) | | packet sequence | - + -### Channel -Channel defines pipeline for exactly-once packet delivery between specific -modules on separate blockchains, which has at least one end capable of -sending packets and one end capable of receiving packets. +### QueryPacketAcknowledgementResponse +QueryPacketAcknowledgementResponse defines the client query response for a +packet which also includes a proof and the height from which the +proof was retrieved | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `state` | [State](#ibc.core.channel.v1.State) | | current state of the channel end | -| `ordering` | [Order](#ibc.core.channel.v1.Order) | | whether the channel is ordered or unordered | -| `counterparty` | [Counterparty](#ibc.core.channel.v1.Counterparty) | | counterparty channel end | -| `connection_hops` | [string](#string) | repeated | list of connection identifiers, in order, along which packets sent on this channel will travel | -| `version` | [string](#string) | | opaque channel version, which is agreed upon during the handshake | +| `acknowledgement` | [bytes](#bytes) | | packet associated with the request fields | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - + -### Counterparty -Counterparty defines a channel end counterparty +### QueryPacketAcknowledgementsRequest +QueryPacketAcknowledgementsRequest is the request type for the +Query/QueryPacketCommitments RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port on the counterparty chain which owns the other end of the channel. | -| `channel_id` | [string](#string) | | channel end on the counterparty chain | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - + -### IdentifiedChannel -IdentifiedChannel defines a channel with additional port and channel -identifier fields. +### QueryPacketAcknowledgementsResponse +QueryPacketAcknowledgemetsResponse is the request type for the +Query/QueryPacketAcknowledgements RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `state` | [State](#ibc.core.channel.v1.State) | | current state of the channel end | -| `ordering` | [Order](#ibc.core.channel.v1.Order) | | whether the channel is ordered or unordered | -| `counterparty` | [Counterparty](#ibc.core.channel.v1.Counterparty) | | counterparty channel end | -| `connection_hops` | [string](#string) | repeated | list of connection identifiers, in order, along which packets sent on this channel will travel | -| `version` | [string](#string) | | opaque channel version, which is agreed upon during the handshake | -| `port_id` | [string](#string) | | port identifier | -| `channel_id` | [string](#string) | | channel identifier | +| `acknowledgements` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | - + -### Packet -Packet defines a type that carries data across different chains through IBC +### QueryPacketCommitmentRequest +QueryPacketCommitmentRequest is the request type for the +Query/PacketCommitment RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `sequence` | [uint64](#uint64) | | number corresponds to the order of sends and receives, where a Packet with an earlier sequence number must be sent and received before a Packet with a later sequence number. | -| `source_port` | [string](#string) | | identifies the port on the sending chain. | -| `source_channel` | [string](#string) | | identifies the channel end on the sending chain. | -| `destination_port` | [string](#string) | | identifies the port on the receiving chain. | -| `destination_channel` | [string](#string) | | identifies the channel end on the receiving chain. | -| `data` | [bytes](#bytes) | | actual opaque bytes transferred directly to the application module | -| `timeout_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | block height after which the packet times out | -| `timeout_timestamp` | [uint64](#uint64) | | block timestamp (in nanoseconds) after which the packet times out | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `sequence` | [uint64](#uint64) | | packet sequence | - + -### PacketState -PacketState defines the generic type necessary to retrieve and store -packet commitments, acknowledgements, and receipts. -Caller is responsible for knowing the context necessary to interpret this -state as a commitment, acknowledgement, or a receipt. +### QueryPacketCommitmentResponse +QueryPacketCommitmentResponse defines the client query response for a packet +which also includes a proof and the height from which the proof was +retrieved | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | channel port identifier. | -| `channel_id` | [string](#string) | | channel unique identifier. | -| `sequence` | [uint64](#uint64) | | packet sequence. | -| `data` | [bytes](#bytes) | | embedded data that represents packet state. | - +| `commitment` | [bytes](#bytes) | | packet associated with the request fields | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - - + -### Order -Order defines if a channel is ORDERED or UNORDERED +### QueryPacketCommitmentsRequest +QueryPacketCommitmentsRequest is the request type for the +Query/QueryPacketCommitments RPC method -| Name | Number | Description | -| ---- | ------ | ----------- | -| ORDER_NONE_UNSPECIFIED | 0 | zero-value for channel ordering | -| ORDER_UNORDERED | 1 | packets can be delivered in any order, which may differ from the order in which they were sent. | -| ORDER_ORDERED | 2 | packets are delivered exactly in the order which they were sent | +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - -### State -State defines if a channel is in one of the following states: -CLOSED, INIT, TRYOPEN, OPEN or UNINITIALIZED. -| Name | Number | Description | -| ---- | ------ | ----------- | -| STATE_UNINITIALIZED_UNSPECIFIED | 0 | Default State | -| STATE_INIT | 1 | A channel has just started the opening handshake. | -| STATE_TRYOPEN | 2 | A channel has acknowledged the handshake step on the counterparty chain. | -| STATE_OPEN | 3 | A channel has completed the handshake. Open channels are ready to send and receive packets. | -| STATE_CLOSED | 4 | A channel has been closed and can no longer be used to send or receive packets. | - + - +### QueryPacketCommitmentsResponse +QueryPacketCommitmentsResponse is the request type for the +Query/QueryPacketCommitments RPC method - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `commitments` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | - -

      Top

      -## ibc/core/channel/v1/query.proto - + -### QueryChannelClientStateRequest -QueryChannelClientStateRequest is the request type for the Query/ClientState -RPC method +### QueryPacketReceiptRequest +QueryPacketReceiptRequest is the request type for the +Query/PacketReceipt RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `port_id` | [string](#string) | | port unique identifier | | `channel_id` | [string](#string) | | channel unique identifier | +| `sequence` | [uint64](#uint64) | | packet sequence | - + -### QueryChannelClientStateResponse -QueryChannelClientStateResponse is the Response type for the -Query/QueryChannelClientState RPC method +### QueryPacketReceiptResponse +QueryPacketReceiptResponse defines the client query response for a packet receipt +which also includes a proof, and the height from which the proof was +retrieved | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `identified_client_state` | [ibc.core.client.v1.IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | | client state associated with the channel | +| `received` | [bool](#bool) | | success flag for if receipt exists | | `proof` | [bytes](#bytes) | | merkle proof of existence | | `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | @@ -8671,428 +8683,404 @@ Query/QueryChannelClientState RPC method - + -### QueryChannelConsensusStateRequest -QueryChannelConsensusStateRequest is the request type for the -Query/ConsensusState RPC method +### QueryUnreceivedAcksRequest +QueryUnreceivedAcks is the request type for the +Query/UnreceivedAcks RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `port_id` | [string](#string) | | port unique identifier | | `channel_id` | [string](#string) | | channel unique identifier | -| `revision_number` | [uint64](#uint64) | | revision number of the consensus state | -| `revision_height` | [uint64](#uint64) | | revision height of the consensus state | +| `packet_ack_sequences` | [uint64](#uint64) | repeated | list of acknowledgement sequences | - + -### QueryChannelConsensusStateResponse -QueryChannelClientStateResponse is the Response type for the -Query/QueryChannelClientState RPC method +### QueryUnreceivedAcksResponse +QueryUnreceivedAcksResponse is the response type for the +Query/UnreceivedAcks RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the channel | -| `client_id` | [string](#string) | | client ID associated with the consensus state | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | +| `sequences` | [uint64](#uint64) | repeated | list of unreceived acknowledgement sequences | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | - + -### QueryChannelRequest -QueryChannelRequest is the request type for the Query/Channel RPC method +### QueryUnreceivedPacketsRequest +QueryUnreceivedPacketsRequest is the request type for the +Query/UnreceivedPackets RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `port_id` | [string](#string) | | port unique identifier | | `channel_id` | [string](#string) | | channel unique identifier | +| `packet_commitment_sequences` | [uint64](#uint64) | repeated | list of packet sequences | - + -### QueryChannelResponse -QueryChannelResponse is the response type for the Query/Channel RPC method. -Besides the Channel end, it includes a proof and the height from which the -proof was retrieved. +### QueryUnreceivedPacketsResponse +QueryUnreceivedPacketsResponse is the response type for the +Query/UnreceivedPacketCommitments RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `channel` | [Channel](#ibc.core.channel.v1.Channel) | | channel associated with the request identifiers | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | +| `sequences` | [uint64](#uint64) | repeated | list of unreceived packet sequences | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | + - + -### QueryChannelsRequest -QueryChannelsRequest is the request type for the Query/Channels RPC method + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | + +### Query +Query provides defines the gRPC querier service +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Channel` | [QueryChannelRequest](#ibc.core.channel.v1.QueryChannelRequest) | [QueryChannelResponse](#ibc.core.channel.v1.QueryChannelResponse) | Channel queries an IBC Channel. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}| +| `Channels` | [QueryChannelsRequest](#ibc.core.channel.v1.QueryChannelsRequest) | [QueryChannelsResponse](#ibc.core.channel.v1.QueryChannelsResponse) | Channels queries all the IBC channels of a chain. | GET|/ibc/core/channel/v1beta1/channels| +| `ConnectionChannels` | [QueryConnectionChannelsRequest](#ibc.core.channel.v1.QueryConnectionChannelsRequest) | [QueryConnectionChannelsResponse](#ibc.core.channel.v1.QueryConnectionChannelsResponse) | ConnectionChannels queries all the channels associated with a connection end. | GET|/ibc/core/channel/v1beta1/connections/{connection}/channels| +| `ChannelClientState` | [QueryChannelClientStateRequest](#ibc.core.channel.v1.QueryChannelClientStateRequest) | [QueryChannelClientStateResponse](#ibc.core.channel.v1.QueryChannelClientStateResponse) | ChannelClientState queries for the client state for the channel associated with the provided channel identifiers. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/client_state| +| `ChannelConsensusState` | [QueryChannelConsensusStateRequest](#ibc.core.channel.v1.QueryChannelConsensusStateRequest) | [QueryChannelConsensusStateResponse](#ibc.core.channel.v1.QueryChannelConsensusStateResponse) | ChannelConsensusState queries for the consensus state for the channel associated with the provided channel identifiers. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/consensus_state/revision/{revision_number}/height/{revision_height}| +| `PacketCommitment` | [QueryPacketCommitmentRequest](#ibc.core.channel.v1.QueryPacketCommitmentRequest) | [QueryPacketCommitmentResponse](#ibc.core.channel.v1.QueryPacketCommitmentResponse) | PacketCommitment queries a stored packet commitment hash. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/{sequence}| +| `PacketCommitments` | [QueryPacketCommitmentsRequest](#ibc.core.channel.v1.QueryPacketCommitmentsRequest) | [QueryPacketCommitmentsResponse](#ibc.core.channel.v1.QueryPacketCommitmentsResponse) | PacketCommitments returns all the packet commitments hashes associated with a channel. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments| +| `PacketReceipt` | [QueryPacketReceiptRequest](#ibc.core.channel.v1.QueryPacketReceiptRequest) | [QueryPacketReceiptResponse](#ibc.core.channel.v1.QueryPacketReceiptResponse) | PacketReceipt queries if a given packet sequence has been received on the queried chain | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_receipts/{sequence}| +| `PacketAcknowledgement` | [QueryPacketAcknowledgementRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementRequest) | [QueryPacketAcknowledgementResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementResponse) | PacketAcknowledgement queries a stored packet acknowledgement hash. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_acks/{sequence}| +| `PacketAcknowledgements` | [QueryPacketAcknowledgementsRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementsRequest) | [QueryPacketAcknowledgementsResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementsResponse) | PacketAcknowledgements returns all the packet acknowledgements associated with a channel. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_acknowledgements| +| `UnreceivedPackets` | [QueryUnreceivedPacketsRequest](#ibc.core.channel.v1.QueryUnreceivedPacketsRequest) | [QueryUnreceivedPacketsResponse](#ibc.core.channel.v1.QueryUnreceivedPacketsResponse) | UnreceivedPackets returns all the unreceived IBC packets associated with a channel and sequences. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/{packet_commitment_sequences}/unreceived_packets| +| `UnreceivedAcks` | [QueryUnreceivedAcksRequest](#ibc.core.channel.v1.QueryUnreceivedAcksRequest) | [QueryUnreceivedAcksResponse](#ibc.core.channel.v1.QueryUnreceivedAcksResponse) | UnreceivedAcks returns all the unreceived IBC acknowledgements associated with a channel and sequences. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/{packet_ack_sequences}/unreceived_acks| +| `NextSequenceReceive` | [QueryNextSequenceReceiveRequest](#ibc.core.channel.v1.QueryNextSequenceReceiveRequest) | [QueryNextSequenceReceiveResponse](#ibc.core.channel.v1.QueryNextSequenceReceiveResponse) | NextSequenceReceive returns the next receive sequence for a given channel. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/next_sequence| + - + +

      Top

      -### QueryChannelsResponse -QueryChannelsResponse is the response type for the Query/Channels RPC method. +## ibc/core/channel/v1/tx.proto -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `channels` | [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) | repeated | list of stored channels of the chain. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | -| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | + +### MsgAcknowledgement +MsgAcknowledgement receives incoming IBC acknowledgement +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `packet` | [Packet](#ibc.core.channel.v1.Packet) | | | +| `acknowledgement` | [bytes](#bytes) | | | +| `proof_acked` | [bytes](#bytes) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `signer` | [string](#string) | | | - -### QueryConnectionChannelsRequest -QueryConnectionChannelsRequest is the request type for the -Query/QueryConnectionChannels RPC method -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connection` | [string](#string) | | connection unique identifier | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | + +### MsgAcknowledgementResponse +MsgAcknowledgementResponse defines the Msg/Acknowledgement response type. - -### QueryConnectionChannelsResponse -QueryConnectionChannelsResponse is the Response type for the -Query/QueryConnectionChannels RPC method + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `channels` | [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) | repeated | list of channels associated with a connection. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | -| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | +### MsgChannelCloseConfirm +MsgChannelCloseConfirm defines a msg sent by a Relayer to Chain B +to acknowledge the change of channel state to CLOSED on Chain A. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `port_id` | [string](#string) | | | +| `channel_id` | [string](#string) | | | +| `proof_init` | [bytes](#bytes) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `signer` | [string](#string) | | | - -### QueryNextSequenceReceiveRequest -QueryNextSequenceReceiveRequest is the request type for the -Query/QueryNextSequenceReceiveRequest RPC method + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | +### MsgChannelCloseConfirmResponse +MsgChannelCloseConfirmResponse defines the Msg/ChannelCloseConfirm response type. - + -### QueryNextSequenceReceiveResponse -QuerySequenceResponse is the request type for the -Query/QueryNextSequenceReceiveResponse RPC method +### MsgChannelCloseInit +MsgChannelCloseInit defines a msg sent by a Relayer to Chain A +to close a channel with Chain B. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `next_sequence_receive` | [uint64](#uint64) | | next sequence receive number | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | +| `port_id` | [string](#string) | | | +| `channel_id` | [string](#string) | | | +| `signer` | [string](#string) | | | + + + + + + + + +### MsgChannelCloseInitResponse +MsgChannelCloseInitResponse defines the Msg/ChannelCloseInit response type. - + -### QueryPacketAcknowledgementRequest -QueryPacketAcknowledgementRequest is the request type for the -Query/PacketAcknowledgement RPC method +### MsgChannelOpenAck +MsgChannelOpenAck defines a msg sent by a Relayer to Chain A to acknowledge +the change of channel state to TRYOPEN on Chain B. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | -| `sequence` | [uint64](#uint64) | | packet sequence | - - +| `port_id` | [string](#string) | | | +| `channel_id` | [string](#string) | | | +| `counterparty_channel_id` | [string](#string) | | | +| `counterparty_version` | [string](#string) | | | +| `proof_try` | [bytes](#bytes) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `signer` | [string](#string) | | | - -### QueryPacketAcknowledgementResponse -QueryPacketAcknowledgementResponse defines the client query response for a -packet which also includes a proof and the height from which the -proof was retrieved + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `acknowledgement` | [bytes](#bytes) | | packet associated with the request fields | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | +### MsgChannelOpenAckResponse +MsgChannelOpenAckResponse defines the Msg/ChannelOpenAck response type. - + -### QueryPacketAcknowledgementsRequest -QueryPacketAcknowledgementsRequest is the request type for the -Query/QueryPacketCommitments RPC method +### MsgChannelOpenConfirm +MsgChannelOpenConfirm defines a msg sent by a Relayer to Chain B to +acknowledge the change of channel state to OPEN on Chain A. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - - +| `port_id` | [string](#string) | | | +| `channel_id` | [string](#string) | | | +| `proof_ack` | [bytes](#bytes) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `signer` | [string](#string) | | | - -### QueryPacketAcknowledgementsResponse -QueryPacketAcknowledgemetsResponse is the request type for the -Query/QueryPacketAcknowledgements RPC method + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `acknowledgements` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | -| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | +### MsgChannelOpenConfirmResponse +MsgChannelOpenConfirmResponse defines the Msg/ChannelOpenConfirm response type. - + -### QueryPacketCommitmentRequest -QueryPacketCommitmentRequest is the request type for the -Query/PacketCommitment RPC method +### MsgChannelOpenInit +MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It +is called by a relayer on Chain A. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | -| `sequence` | [uint64](#uint64) | | packet sequence | - - +| `port_id` | [string](#string) | | | +| `channel` | [Channel](#ibc.core.channel.v1.Channel) | | | +| `signer` | [string](#string) | | | - -### QueryPacketCommitmentResponse -QueryPacketCommitmentResponse defines the client query response for a packet -which also includes a proof and the height from which the proof was -retrieved + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `commitment` | [bytes](#bytes) | | packet associated with the request fields | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | +### MsgChannelOpenInitResponse +MsgChannelOpenInitResponse defines the Msg/ChannelOpenInit response type. - + -### QueryPacketCommitmentsRequest -QueryPacketCommitmentsRequest is the request type for the -Query/QueryPacketCommitments RPC method +### MsgChannelOpenTry +MsgChannelOpenInit defines a msg sent by a Relayer to try to open a channel +on Chain B. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - - +| `port_id` | [string](#string) | | | +| `previous_channel_id` | [string](#string) | | in the case of crossing hello's, when both chains call OpenInit, we need the channel identifier of the previous channel in state INIT | +| `channel` | [Channel](#ibc.core.channel.v1.Channel) | | | +| `counterparty_version` | [string](#string) | | | +| `proof_init` | [bytes](#bytes) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `signer` | [string](#string) | | | - -### QueryPacketCommitmentsResponse -QueryPacketCommitmentsResponse is the request type for the -Query/QueryPacketCommitments RPC method + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `commitments` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | -| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | +### MsgChannelOpenTryResponse +MsgChannelOpenTryResponse defines the Msg/ChannelOpenTry response type. - + -### QueryPacketReceiptRequest -QueryPacketReceiptRequest is the request type for the -Query/PacketReceipt RPC method +### MsgRecvPacket +MsgRecvPacket receives incoming IBC packet | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | -| `sequence` | [uint64](#uint64) | | packet sequence | - - +| `packet` | [Packet](#ibc.core.channel.v1.Packet) | | | +| `proof_commitment` | [bytes](#bytes) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `signer` | [string](#string) | | | - -### QueryPacketReceiptResponse -QueryPacketReceiptResponse defines the client query response for a packet receipt -which also includes a proof, and the height from which the proof was -retrieved + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `received` | [bool](#bool) | | success flag for if receipt exists | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | +### MsgRecvPacketResponse +MsgRecvPacketResponse defines the Msg/RecvPacket response type. - + -### QueryUnreceivedAcksRequest -QueryUnreceivedAcks is the request type for the -Query/UnreceivedAcks RPC method +### MsgTimeout +MsgTimeout receives timed-out packet | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | -| `packet_ack_sequences` | [uint64](#uint64) | repeated | list of acknowledgement sequences | +| `packet` | [Packet](#ibc.core.channel.v1.Packet) | | | +| `proof_unreceived` | [bytes](#bytes) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `next_sequence_recv` | [uint64](#uint64) | | | +| `signer` | [string](#string) | | | - + -### QueryUnreceivedAcksResponse -QueryUnreceivedAcksResponse is the response type for the -Query/UnreceivedAcks RPC method +### MsgTimeoutOnClose +MsgTimeoutOnClose timed-out packet upon counterparty channel closure. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `sequences` | [uint64](#uint64) | repeated | list of unreceived acknowledgement sequences | -| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | - - - - +| `packet` | [Packet](#ibc.core.channel.v1.Packet) | | | +| `proof_unreceived` | [bytes](#bytes) | | | +| `proof_close` | [bytes](#bytes) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `next_sequence_recv` | [uint64](#uint64) | | | +| `signer` | [string](#string) | | | - -### QueryUnreceivedPacketsRequest -QueryUnreceivedPacketsRequest is the request type for the -Query/UnreceivedPackets RPC method -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | -| `packet_commitment_sequences` | [uint64](#uint64) | repeated | list of packet sequences | + +### MsgTimeoutOnCloseResponse +MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type. - -### QueryUnreceivedPacketsResponse -QueryUnreceivedPacketsResponse is the response type for the -Query/UnreceivedPacketCommitments RPC method + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `sequences` | [uint64](#uint64) | repeated | list of unreceived packet sequences | -| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | +### MsgTimeoutResponse +MsgTimeoutResponse defines the Msg/Timeout response type. @@ -9105,403 +9093,406 @@ Query/UnreceivedPacketCommitments RPC method - + -### Query -Query provides defines the gRPC querier service +### Msg +Msg defines the ibc/channel Msg service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Channel` | [QueryChannelRequest](#ibc.core.channel.v1.QueryChannelRequest) | [QueryChannelResponse](#ibc.core.channel.v1.QueryChannelResponse) | Channel queries an IBC Channel. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}| -| `Channels` | [QueryChannelsRequest](#ibc.core.channel.v1.QueryChannelsRequest) | [QueryChannelsResponse](#ibc.core.channel.v1.QueryChannelsResponse) | Channels queries all the IBC channels of a chain. | GET|/ibc/core/channel/v1beta1/channels| -| `ConnectionChannels` | [QueryConnectionChannelsRequest](#ibc.core.channel.v1.QueryConnectionChannelsRequest) | [QueryConnectionChannelsResponse](#ibc.core.channel.v1.QueryConnectionChannelsResponse) | ConnectionChannels queries all the channels associated with a connection end. | GET|/ibc/core/channel/v1beta1/connections/{connection}/channels| -| `ChannelClientState` | [QueryChannelClientStateRequest](#ibc.core.channel.v1.QueryChannelClientStateRequest) | [QueryChannelClientStateResponse](#ibc.core.channel.v1.QueryChannelClientStateResponse) | ChannelClientState queries for the client state for the channel associated with the provided channel identifiers. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/client_state| -| `ChannelConsensusState` | [QueryChannelConsensusStateRequest](#ibc.core.channel.v1.QueryChannelConsensusStateRequest) | [QueryChannelConsensusStateResponse](#ibc.core.channel.v1.QueryChannelConsensusStateResponse) | ChannelConsensusState queries for the consensus state for the channel associated with the provided channel identifiers. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/consensus_state/revision/{revision_number}/height/{revision_height}| -| `PacketCommitment` | [QueryPacketCommitmentRequest](#ibc.core.channel.v1.QueryPacketCommitmentRequest) | [QueryPacketCommitmentResponse](#ibc.core.channel.v1.QueryPacketCommitmentResponse) | PacketCommitment queries a stored packet commitment hash. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/{sequence}| -| `PacketCommitments` | [QueryPacketCommitmentsRequest](#ibc.core.channel.v1.QueryPacketCommitmentsRequest) | [QueryPacketCommitmentsResponse](#ibc.core.channel.v1.QueryPacketCommitmentsResponse) | PacketCommitments returns all the packet commitments hashes associated with a channel. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments| -| `PacketReceipt` | [QueryPacketReceiptRequest](#ibc.core.channel.v1.QueryPacketReceiptRequest) | [QueryPacketReceiptResponse](#ibc.core.channel.v1.QueryPacketReceiptResponse) | PacketReceipt queries if a given packet sequence has been received on the queried chain | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_receipts/{sequence}| -| `PacketAcknowledgement` | [QueryPacketAcknowledgementRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementRequest) | [QueryPacketAcknowledgementResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementResponse) | PacketAcknowledgement queries a stored packet acknowledgement hash. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_acks/{sequence}| -| `PacketAcknowledgements` | [QueryPacketAcknowledgementsRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementsRequest) | [QueryPacketAcknowledgementsResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementsResponse) | PacketAcknowledgements returns all the packet acknowledgements associated with a channel. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_acknowledgements| -| `UnreceivedPackets` | [QueryUnreceivedPacketsRequest](#ibc.core.channel.v1.QueryUnreceivedPacketsRequest) | [QueryUnreceivedPacketsResponse](#ibc.core.channel.v1.QueryUnreceivedPacketsResponse) | UnreceivedPackets returns all the unreceived IBC packets associated with a channel and sequences. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/{packet_commitment_sequences}/unreceived_packets| -| `UnreceivedAcks` | [QueryUnreceivedAcksRequest](#ibc.core.channel.v1.QueryUnreceivedAcksRequest) | [QueryUnreceivedAcksResponse](#ibc.core.channel.v1.QueryUnreceivedAcksResponse) | UnreceivedAcks returns all the unreceived IBC acknowledgements associated with a channel and sequences. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/{packet_ack_sequences}/unreceived_acks| -| `NextSequenceReceive` | [QueryNextSequenceReceiveRequest](#ibc.core.channel.v1.QueryNextSequenceReceiveRequest) | [QueryNextSequenceReceiveResponse](#ibc.core.channel.v1.QueryNextSequenceReceiveResponse) | NextSequenceReceive returns the next receive sequence for a given channel. | GET|/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/next_sequence| +| `ChannelOpenInit` | [MsgChannelOpenInit](#ibc.core.channel.v1.MsgChannelOpenInit) | [MsgChannelOpenInitResponse](#ibc.core.channel.v1.MsgChannelOpenInitResponse) | ChannelOpenInit defines a rpc handler method for MsgChannelOpenInit. | | +| `ChannelOpenTry` | [MsgChannelOpenTry](#ibc.core.channel.v1.MsgChannelOpenTry) | [MsgChannelOpenTryResponse](#ibc.core.channel.v1.MsgChannelOpenTryResponse) | ChannelOpenTry defines a rpc handler method for MsgChannelOpenTry. | | +| `ChannelOpenAck` | [MsgChannelOpenAck](#ibc.core.channel.v1.MsgChannelOpenAck) | [MsgChannelOpenAckResponse](#ibc.core.channel.v1.MsgChannelOpenAckResponse) | ChannelOpenAck defines a rpc handler method for MsgChannelOpenAck. | | +| `ChannelOpenConfirm` | [MsgChannelOpenConfirm](#ibc.core.channel.v1.MsgChannelOpenConfirm) | [MsgChannelOpenConfirmResponse](#ibc.core.channel.v1.MsgChannelOpenConfirmResponse) | ChannelOpenConfirm defines a rpc handler method for MsgChannelOpenConfirm. | | +| `ChannelCloseInit` | [MsgChannelCloseInit](#ibc.core.channel.v1.MsgChannelCloseInit) | [MsgChannelCloseInitResponse](#ibc.core.channel.v1.MsgChannelCloseInitResponse) | ChannelCloseInit defines a rpc handler method for MsgChannelCloseInit. | | +| `ChannelCloseConfirm` | [MsgChannelCloseConfirm](#ibc.core.channel.v1.MsgChannelCloseConfirm) | [MsgChannelCloseConfirmResponse](#ibc.core.channel.v1.MsgChannelCloseConfirmResponse) | ChannelCloseConfirm defines a rpc handler method for MsgChannelCloseConfirm. | | +| `RecvPacket` | [MsgRecvPacket](#ibc.core.channel.v1.MsgRecvPacket) | [MsgRecvPacketResponse](#ibc.core.channel.v1.MsgRecvPacketResponse) | RecvPacket defines a rpc handler method for MsgRecvPacket. | | +| `Timeout` | [MsgTimeout](#ibc.core.channel.v1.MsgTimeout) | [MsgTimeoutResponse](#ibc.core.channel.v1.MsgTimeoutResponse) | Timeout defines a rpc handler method for MsgTimeout. | | +| `TimeoutOnClose` | [MsgTimeoutOnClose](#ibc.core.channel.v1.MsgTimeoutOnClose) | [MsgTimeoutOnCloseResponse](#ibc.core.channel.v1.MsgTimeoutOnCloseResponse) | TimeoutOnClose defines a rpc handler method for MsgTimeoutOnClose. | | +| `Acknowledgement` | [MsgAcknowledgement](#ibc.core.channel.v1.MsgAcknowledgement) | [MsgAcknowledgementResponse](#ibc.core.channel.v1.MsgAcknowledgementResponse) | Acknowledgement defines a rpc handler method for MsgAcknowledgement. | | - +

      Top

      -## ibc/core/channel/v1/tx.proto +## ibc/core/client/v1/genesis.proto - + -### MsgAcknowledgement -MsgAcknowledgement receives incoming IBC acknowledgement +### GenesisMetadata +GenesisMetadata defines the genesis type for metadata that clients may return +with ExportMetadata | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `packet` | [Packet](#ibc.core.channel.v1.Packet) | | | -| `acknowledgement` | [bytes](#bytes) | | | -| `proof_acked` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | +| `key` | [bytes](#bytes) | | store key of metadata without clientID-prefix | +| `value` | [bytes](#bytes) | | metadata value | - + -### MsgAcknowledgementResponse -MsgAcknowledgementResponse defines the Msg/Acknowledgement response type. +### GenesisState +GenesisState defines the ibc client submodule's genesis state. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `clients` | [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | repeated | client states with their corresponding identifiers | +| `clients_consensus` | [ClientConsensusStates](#ibc.core.client.v1.ClientConsensusStates) | repeated | consensus states from each client | +| `clients_metadata` | [IdentifiedGenesisMetadata](#ibc.core.client.v1.IdentifiedGenesisMetadata) | repeated | metadata from each client | +| `params` | [Params](#ibc.core.client.v1.Params) | | | +| `create_localhost` | [bool](#bool) | | create localhost on initialization | +| `next_client_sequence` | [uint64](#uint64) | | the sequence for the next generated client identifier | - -### MsgChannelCloseConfirm -MsgChannelCloseConfirm defines a msg sent by a Relayer to Chain B -to acknowledge the change of channel state to CLOSED on Chain A. + + + +### IdentifiedGenesisMetadata +IdentifiedGenesisMetadata has the client metadata with the corresponding client id. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel_id` | [string](#string) | | | -| `proof_init` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | +| `client_id` | [string](#string) | | | +| `client_metadata` | [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) | repeated | | + - + -### MsgChannelCloseConfirmResponse -MsgChannelCloseConfirmResponse defines the Msg/ChannelCloseConfirm response type. + + + +

      Top

      +## ibc/core/client/v1/query.proto - -### MsgChannelCloseInit -MsgChannelCloseInit defines a msg sent by a Relayer to Chain A -to close a channel with Chain B. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel_id` | [string](#string) | | | -| `signer` | [string](#string) | | | +### QueryClientParamsRequest +QueryClientParamsRequest is the request type for the Query/ClientParams RPC method. - + -### MsgChannelCloseInitResponse -MsgChannelCloseInitResponse defines the Msg/ChannelCloseInit response type. +### QueryClientParamsResponse +QueryClientParamsResponse is the response type for the Query/ClientParams RPC method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params` | [Params](#ibc.core.client.v1.Params) | | params defines the parameters of the module. | - -### MsgChannelOpenAck -MsgChannelOpenAck defines a msg sent by a Relayer to Chain A to acknowledge -the change of channel state to TRYOPEN on Chain B. + + + +### QueryClientStateRequest +QueryClientStateRequest is the request type for the Query/ClientState RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel_id` | [string](#string) | | | -| `counterparty_channel_id` | [string](#string) | | | -| `counterparty_version` | [string](#string) | | | -| `proof_try` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | +| `client_id` | [string](#string) | | client state unique identifier | - + -### MsgChannelOpenAckResponse -MsgChannelOpenAckResponse defines the Msg/ChannelOpenAck response type. +### QueryClientStateResponse +QueryClientStateResponse is the response type for the Query/ClientState RPC +method. Besides the client state, it includes a proof and the height from +which the proof was retrieved. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | client state associated with the request identifier | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - -### MsgChannelOpenConfirm -MsgChannelOpenConfirm defines a msg sent by a Relayer to Chain B to -acknowledge the change of channel state to OPEN on Chain A. + + + +### QueryClientStatesRequest +QueryClientStatesRequest is the request type for the Query/ClientStates RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel_id` | [string](#string) | | | -| `proof_ack` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - + -### MsgChannelOpenConfirmResponse -MsgChannelOpenConfirmResponse defines the Msg/ChannelOpenConfirm response type. +### QueryClientStatesResponse +QueryClientStatesResponse is the response type for the Query/ClientStates RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_states` | [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | repeated | list of stored ClientStates of the chain. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | - + -### MsgChannelOpenInit -MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It -is called by a relayer on Chain A. +### QueryConsensusStateRequest +QueryConsensusStateRequest is the request type for the Query/ConsensusState +RPC method. Besides the consensus state, it includes a proof and the height +from which the proof was retrieved. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel` | [Channel](#ibc.core.channel.v1.Channel) | | | -| `signer` | [string](#string) | | | +| `client_id` | [string](#string) | | client identifier | +| `revision_number` | [uint64](#uint64) | | consensus state revision number | +| `revision_height` | [uint64](#uint64) | | consensus state revision height | +| `latest_height` | [bool](#bool) | | latest_height overrrides the height field and queries the latest stored ConsensusState | - + -### MsgChannelOpenInitResponse -MsgChannelOpenInitResponse defines the Msg/ChannelOpenInit response type. +### QueryConsensusStateResponse +QueryConsensusStateResponse is the response type for the Query/ConsensusState +RPC method +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the client identifier at the given height | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - -### MsgChannelOpenTry -MsgChannelOpenInit defines a msg sent by a Relayer to try to open a channel -on Chain B. + + + +### QueryConsensusStatesRequest +QueryConsensusStatesRequest is the request type for the Query/ConsensusStates +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `previous_channel_id` | [string](#string) | | in the case of crossing hello's, when both chains call OpenInit, we need the channel identifier of the previous channel in state INIT | -| `channel` | [Channel](#ibc.core.channel.v1.Channel) | | | -| `counterparty_version` | [string](#string) | | | -| `proof_init` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | - +| `client_id` | [string](#string) | | client identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - -### MsgChannelOpenTryResponse -MsgChannelOpenTryResponse defines the Msg/ChannelOpenTry response type. + +### QueryConsensusStatesResponse +QueryConsensusStatesResponse is the response type for the +Query/ConsensusStates RPC method +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `consensus_states` | [ConsensusStateWithHeight](#ibc.core.client.v1.ConsensusStateWithHeight) | repeated | consensus states associated with the identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | - -### MsgRecvPacket -MsgRecvPacket receives incoming IBC packet + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `packet` | [Packet](#ibc.core.channel.v1.Packet) | | | -| `proof_commitment` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | + + + +### Query +Query provides defines the gRPC querier service +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `ClientState` | [QueryClientStateRequest](#ibc.core.client.v1.QueryClientStateRequest) | [QueryClientStateResponse](#ibc.core.client.v1.QueryClientStateResponse) | ClientState queries an IBC light client. | GET|/ibc/core/client/v1beta1/client_states/{client_id}| +| `ClientStates` | [QueryClientStatesRequest](#ibc.core.client.v1.QueryClientStatesRequest) | [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse) | ClientStates queries all the IBC light clients of a chain. | GET|/ibc/core/client/v1beta1/client_states| +| `ConsensusState` | [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest) | [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) | ConsensusState queries a consensus state associated with a client state at a given height. | GET|/ibc/core/client/v1beta1/consensus_states/{client_id}/revision/{revision_number}/height/{revision_height}| +| `ConsensusStates` | [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) | [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) | ConsensusStates queries all the consensus state associated with a given client. | GET|/ibc/core/client/v1beta1/consensus_states/{client_id}| +| `ClientParams` | [QueryClientParamsRequest](#ibc.core.client.v1.QueryClientParamsRequest) | [QueryClientParamsResponse](#ibc.core.client.v1.QueryClientParamsResponse) | ClientParams queries all parameters of the ibc client. | GET|/ibc/client/v1beta1/params| - + -### MsgRecvPacketResponse -MsgRecvPacketResponse defines the Msg/RecvPacket response type. + +

      Top

      +## ibc/core/client/v1/tx.proto - + -### MsgTimeout -MsgTimeout receives timed-out packet +### MsgCreateClient +MsgCreateClient defines a message to create an IBC client | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `packet` | [Packet](#ibc.core.channel.v1.Packet) | | | -| `proof_unreceived` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `next_sequence_recv` | [uint64](#uint64) | | | -| `signer` | [string](#string) | | | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | light client state | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the client that corresponds to a given height. | +| `signer` | [string](#string) | | signer address | - + + +### MsgCreateClientResponse +MsgCreateClientResponse defines the Msg/CreateClient response type. + -### MsgTimeoutOnClose -MsgTimeoutOnClose timed-out packet upon counterparty channel closure. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `packet` | [Packet](#ibc.core.channel.v1.Packet) | | | -| `proof_unreceived` | [bytes](#bytes) | | | -| `proof_close` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `next_sequence_recv` | [uint64](#uint64) | | | -| `signer` | [string](#string) | | | + + +### MsgSubmitMisbehaviour +MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for +light client misbehaviour. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client unique identifier | +| `misbehaviour` | [google.protobuf.Any](#google.protobuf.Any) | | misbehaviour used for freezing the light client | +| `signer` | [string](#string) | | signer address | - -### MsgTimeoutOnCloseResponse -MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type. + +### MsgSubmitMisbehaviourResponse +MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response type. - -### MsgTimeoutResponse -MsgTimeoutResponse defines the Msg/Timeout response type. + +### MsgUpdateClient +MsgUpdateClient defines an sdk.Msg to update a IBC client state using +the given header. - - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client unique identifier | +| `header` | [google.protobuf.Any](#google.protobuf.Any) | | header to update the light client | +| `signer` | [string](#string) | | signer address | - - -### Msg -Msg defines the ibc/channel Msg service. -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `ChannelOpenInit` | [MsgChannelOpenInit](#ibc.core.channel.v1.MsgChannelOpenInit) | [MsgChannelOpenInitResponse](#ibc.core.channel.v1.MsgChannelOpenInitResponse) | ChannelOpenInit defines a rpc handler method for MsgChannelOpenInit. | | -| `ChannelOpenTry` | [MsgChannelOpenTry](#ibc.core.channel.v1.MsgChannelOpenTry) | [MsgChannelOpenTryResponse](#ibc.core.channel.v1.MsgChannelOpenTryResponse) | ChannelOpenTry defines a rpc handler method for MsgChannelOpenTry. | | -| `ChannelOpenAck` | [MsgChannelOpenAck](#ibc.core.channel.v1.MsgChannelOpenAck) | [MsgChannelOpenAckResponse](#ibc.core.channel.v1.MsgChannelOpenAckResponse) | ChannelOpenAck defines a rpc handler method for MsgChannelOpenAck. | | -| `ChannelOpenConfirm` | [MsgChannelOpenConfirm](#ibc.core.channel.v1.MsgChannelOpenConfirm) | [MsgChannelOpenConfirmResponse](#ibc.core.channel.v1.MsgChannelOpenConfirmResponse) | ChannelOpenConfirm defines a rpc handler method for MsgChannelOpenConfirm. | | -| `ChannelCloseInit` | [MsgChannelCloseInit](#ibc.core.channel.v1.MsgChannelCloseInit) | [MsgChannelCloseInitResponse](#ibc.core.channel.v1.MsgChannelCloseInitResponse) | ChannelCloseInit defines a rpc handler method for MsgChannelCloseInit. | | -| `ChannelCloseConfirm` | [MsgChannelCloseConfirm](#ibc.core.channel.v1.MsgChannelCloseConfirm) | [MsgChannelCloseConfirmResponse](#ibc.core.channel.v1.MsgChannelCloseConfirmResponse) | ChannelCloseConfirm defines a rpc handler method for MsgChannelCloseConfirm. | | -| `RecvPacket` | [MsgRecvPacket](#ibc.core.channel.v1.MsgRecvPacket) | [MsgRecvPacketResponse](#ibc.core.channel.v1.MsgRecvPacketResponse) | RecvPacket defines a rpc handler method for MsgRecvPacket. | | -| `Timeout` | [MsgTimeout](#ibc.core.channel.v1.MsgTimeout) | [MsgTimeoutResponse](#ibc.core.channel.v1.MsgTimeoutResponse) | Timeout defines a rpc handler method for MsgTimeout. | | -| `TimeoutOnClose` | [MsgTimeoutOnClose](#ibc.core.channel.v1.MsgTimeoutOnClose) | [MsgTimeoutOnCloseResponse](#ibc.core.channel.v1.MsgTimeoutOnCloseResponse) | TimeoutOnClose defines a rpc handler method for MsgTimeoutOnClose. | | -| `Acknowledgement` | [MsgAcknowledgement](#ibc.core.channel.v1.MsgAcknowledgement) | [MsgAcknowledgementResponse](#ibc.core.channel.v1.MsgAcknowledgementResponse) | Acknowledgement defines a rpc handler method for MsgAcknowledgement. | | - + +### MsgUpdateClientResponse +MsgUpdateClientResponse defines the Msg/UpdateClient response type. - -

      Top

      -## ibc/core/channel/v1/genesis.proto - + -### GenesisState -GenesisState defines the ibc channel submodule's genesis state. +### MsgUpgradeClient +MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `channels` | [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) | repeated | | -| `acknowledgements` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | -| `commitments` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | -| `receipts` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | -| `send_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | -| `recv_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | -| `ack_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | -| `next_channel_sequence` | [uint64](#uint64) | | the sequence for the next generated channel identifier | - - +| `client_id` | [string](#string) | | client unique identifier | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | upgraded client state | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | upgraded consensus state, only contains enough information to serve as a basis of trust in update logic | +| `proof_upgrade_client` | [bytes](#bytes) | | proof that old chain committed to new client | +| `proof_upgrade_consensus_state` | [bytes](#bytes) | | proof that old chain committed to new consensus state | +| `signer` | [string](#string) | | signer address | - -### PacketSequence -PacketSequence defines the genesis type necessary to retrieve and store -next send and receive sequences. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel_id` | [string](#string) | | | -| `sequence` | [uint64](#uint64) | | | +### MsgUpgradeClientResponse +MsgUpgradeClientResponse defines the Msg/UpgradeClient response type. @@ -9513,6 +9504,19 @@ next send and receive sequences. + + + +### Msg +Msg defines the ibc/client Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `CreateClient` | [MsgCreateClient](#ibc.core.client.v1.MsgCreateClient) | [MsgCreateClientResponse](#ibc.core.client.v1.MsgCreateClientResponse) | CreateClient defines a rpc handler method for MsgCreateClient. | | +| `UpdateClient` | [MsgUpdateClient](#ibc.core.client.v1.MsgUpdateClient) | [MsgUpdateClientResponse](#ibc.core.client.v1.MsgUpdateClientResponse) | UpdateClient defines a rpc handler method for MsgUpdateClient. | | +| `UpgradeClient` | [MsgUpgradeClient](#ibc.core.client.v1.MsgUpgradeClient) | [MsgUpgradeClientResponse](#ibc.core.client.v1.MsgUpgradeClientResponse) | UpgradeClient defines a rpc handler method for MsgUpgradeClient. | | +| `SubmitMisbehaviour` | [MsgSubmitMisbehaviour](#ibc.core.client.v1.MsgSubmitMisbehaviour) | [MsgSubmitMisbehaviourResponse](#ibc.core.client.v1.MsgSubmitMisbehaviourResponse) | SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour. | | + @@ -9741,6 +9745,39 @@ INIT, TRYOPEN, OPEN or UNINITIALIZED. + +

      Top

      + +## ibc/core/connection/v1/genesis.proto + + + + + +### GenesisState +GenesisState defines the ibc connection submodule's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `connections` | [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) | repeated | | +| `client_connection_paths` | [ConnectionPaths](#ibc.core.connection.v1.ConnectionPaths) | repeated | | +| `next_connection_sequence` | [uint64](#uint64) | | the sequence for the next generated connection identifier | + + + + + + + + + + + + + + +

      Top

      @@ -10036,281 +10073,126 @@ initialize a connection with Chain B. - - -### MsgConnectionOpenInitResponse -MsgConnectionOpenInitResponse defines the Msg/ConnectionOpenInit response type. - - - - - - - - -### MsgConnectionOpenTry -MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a -connection on Chain B. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `previous_connection_id` | [string](#string) | | in the case of crossing hello's, when both chains call OpenInit, we need the connection identifier of the previous connection in state INIT | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | | -| `delay_period` | [uint64](#uint64) | | | -| `counterparty_versions` | [Version](#ibc.core.connection.v1.Version) | repeated | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `proof_init` | [bytes](#bytes) | | proof of the initialization the connection on Chain A: `UNITIALIZED -> INIT` | -| `proof_client` | [bytes](#bytes) | | proof of client state included in message | -| `proof_consensus` | [bytes](#bytes) | | proof of client consensus state | -| `consensus_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | - - - - - - - - -### MsgConnectionOpenTryResponse -MsgConnectionOpenTryResponse defines the Msg/ConnectionOpenTry response type. - - - - - - - - - - - - - - -### Msg -Msg defines the ibc/connection Msg service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `ConnectionOpenInit` | [MsgConnectionOpenInit](#ibc.core.connection.v1.MsgConnectionOpenInit) | [MsgConnectionOpenInitResponse](#ibc.core.connection.v1.MsgConnectionOpenInitResponse) | ConnectionOpenInit defines a rpc handler method for MsgConnectionOpenInit. | | -| `ConnectionOpenTry` | [MsgConnectionOpenTry](#ibc.core.connection.v1.MsgConnectionOpenTry) | [MsgConnectionOpenTryResponse](#ibc.core.connection.v1.MsgConnectionOpenTryResponse) | ConnectionOpenTry defines a rpc handler method for MsgConnectionOpenTry. | | -| `ConnectionOpenAck` | [MsgConnectionOpenAck](#ibc.core.connection.v1.MsgConnectionOpenAck) | [MsgConnectionOpenAckResponse](#ibc.core.connection.v1.MsgConnectionOpenAckResponse) | ConnectionOpenAck defines a rpc handler method for MsgConnectionOpenAck. | | -| `ConnectionOpenConfirm` | [MsgConnectionOpenConfirm](#ibc.core.connection.v1.MsgConnectionOpenConfirm) | [MsgConnectionOpenConfirmResponse](#ibc.core.connection.v1.MsgConnectionOpenConfirmResponse) | ConnectionOpenConfirm defines a rpc handler method for MsgConnectionOpenConfirm. | | - - - - - - -

      Top

      - -## ibc/core/connection/v1/genesis.proto - - - - - -### GenesisState -GenesisState defines the ibc connection submodule's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connections` | [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) | repeated | | -| `client_connection_paths` | [ConnectionPaths](#ibc.core.connection.v1.ConnectionPaths) | repeated | | -| `next_connection_sequence` | [uint64](#uint64) | | the sequence for the next generated connection identifier | - - - - - - - - - - - - - - - - -

      Top

      - -## ibc/core/types/v1/genesis.proto - - - - - -### GenesisState -GenesisState defines the ibc module's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_genesis` | [ibc.core.client.v1.GenesisState](#ibc.core.client.v1.GenesisState) | | ICS002 - Clients genesis state | -| `connection_genesis` | [ibc.core.connection.v1.GenesisState](#ibc.core.connection.v1.GenesisState) | | ICS003 - Connections genesis state | -| `channel_genesis` | [ibc.core.channel.v1.GenesisState](#ibc.core.channel.v1.GenesisState) | | ICS004 - Channel genesis state | - - - - - - - - - - - - - - - - -

      Top

      - -## ibc/lightclients/localhost/v1/localhost.proto - - - - + -### ClientState -ClientState defines a loopback (localhost) client. It requires (read-only) -access to keys outside the client prefix. +### MsgConnectionOpenInitResponse +MsgConnectionOpenInitResponse defines the Msg/ConnectionOpenInit response type. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `chain_id` | [string](#string) | | self chain ID | -| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | self latest block height | + - +### MsgConnectionOpenTry +MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a +connection on Chain B. - - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | | +| `previous_connection_id` | [string](#string) | | in the case of crossing hello's, when both chains call OpenInit, we need the connection identifier of the previous connection in state INIT | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | | +| `delay_period` | [uint64](#uint64) | | | +| `counterparty_versions` | [Version](#ibc.core.connection.v1.Version) | repeated | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `proof_init` | [bytes](#bytes) | | proof of the initialization the connection on Chain A: `UNITIALIZED -> INIT` | +| `proof_client` | [bytes](#bytes) | | proof of client state included in message | +| `proof_consensus` | [bytes](#bytes) | | proof of client consensus state | +| `consensus_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `signer` | [string](#string) | | | - - -

      Top

      -## ibc/lightclients/tendermint/v1/tendermint.proto + +### MsgConnectionOpenTryResponse +MsgConnectionOpenTryResponse defines the Msg/ConnectionOpenTry response type. - -### ClientState -ClientState from Tendermint tracks the current validator set, latest height, -and a possible frozen height. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `chain_id` | [string](#string) | | | -| `trust_level` | [Fraction](#ibc.lightclients.tendermint.v1.Fraction) | | | -| `trusting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | duration of the period since the LastestTimestamp during which the submitted headers are valid for upgrade | -| `unbonding_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | duration of the staking unbonding period | -| `max_clock_drift` | [google.protobuf.Duration](#google.protobuf.Duration) | | defines how much new (untrusted) header's Time can drift into the future. | -| `frozen_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Block height when the client was frozen due to a misbehaviour | -| `latest_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Latest height the client was updated to | -| `proof_specs` | [ics23.ProofSpec](#ics23.ProofSpec) | repeated | Proof specifications used in verifying counterparty state | -| `upgrade_path` | [string](#string) | repeated | Path at which next upgraded client will be committed. Each element corresponds to the key for a single CommitmentProof in the chained proof. NOTE: ClientState must stored under `{upgradePath}/{upgradeHeight}/clientState` ConsensusState must be stored under `{upgradepath}/{upgradeHeight}/consensusState` For SDK chains using the default upgrade module, upgrade_path should be []string{"upgrade", "upgradedIBCState"}` | -| `allow_update_after_expiry` | [bool](#bool) | | This flag, when set to true, will allow governance to recover a client which has expired | -| `allow_update_after_misbehaviour` | [bool](#bool) | | This flag, when set to true, will allow governance to unfreeze a client whose chain has experienced a misbehaviour event | + + + + - +### Msg +Msg defines the ibc/connection Msg service. -### ConsensusState -ConsensusState defines the consensus state from Tendermint. +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `ConnectionOpenInit` | [MsgConnectionOpenInit](#ibc.core.connection.v1.MsgConnectionOpenInit) | [MsgConnectionOpenInitResponse](#ibc.core.connection.v1.MsgConnectionOpenInitResponse) | ConnectionOpenInit defines a rpc handler method for MsgConnectionOpenInit. | | +| `ConnectionOpenTry` | [MsgConnectionOpenTry](#ibc.core.connection.v1.MsgConnectionOpenTry) | [MsgConnectionOpenTryResponse](#ibc.core.connection.v1.MsgConnectionOpenTryResponse) | ConnectionOpenTry defines a rpc handler method for MsgConnectionOpenTry. | | +| `ConnectionOpenAck` | [MsgConnectionOpenAck](#ibc.core.connection.v1.MsgConnectionOpenAck) | [MsgConnectionOpenAckResponse](#ibc.core.connection.v1.MsgConnectionOpenAckResponse) | ConnectionOpenAck defines a rpc handler method for MsgConnectionOpenAck. | | +| `ConnectionOpenConfirm` | [MsgConnectionOpenConfirm](#ibc.core.connection.v1.MsgConnectionOpenConfirm) | [MsgConnectionOpenConfirmResponse](#ibc.core.connection.v1.MsgConnectionOpenConfirmResponse) | ConnectionOpenConfirm defines a rpc handler method for MsgConnectionOpenConfirm. | | + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `timestamp` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | timestamp that corresponds to the block height in which the ConsensusState was stored. | -| `root` | [ibc.core.commitment.v1.MerkleRoot](#ibc.core.commitment.v1.MerkleRoot) | | commitment root (i.e app hash) | -| `next_validators_hash` | [bytes](#bytes) | | | + +

      Top

      +## ibc/core/types/v1/genesis.proto - + -### Fraction -Fraction defines the protobuf message type for tmmath.Fraction that only supports positive values. +### GenesisState +GenesisState defines the ibc module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `numerator` | [uint64](#uint64) | | | -| `denominator` | [uint64](#uint64) | | | +| `client_genesis` | [ibc.core.client.v1.GenesisState](#ibc.core.client.v1.GenesisState) | | ICS002 - Clients genesis state | +| `connection_genesis` | [ibc.core.connection.v1.GenesisState](#ibc.core.connection.v1.GenesisState) | | ICS003 - Connections genesis state | +| `channel_genesis` | [ibc.core.channel.v1.GenesisState](#ibc.core.channel.v1.GenesisState) | | ICS004 - Channel genesis state | + - + -### Header -Header defines the Tendermint client consensus Header. -It encapsulates all the information necessary to update from a trusted -Tendermint ConsensusState. The inclusion of TrustedHeight and -TrustedValidators allows this update to process correctly, so long as the -ConsensusState for the TrustedHeight exists, this removes race conditions -among relayers The SignedHeader and ValidatorSet are the new untrusted update -fields for the client. The TrustedHeight is the height of a stored -ConsensusState on the client that will be used to verify the new untrusted -header. The Trusted ConsensusState must be within the unbonding period of -current time in order to correctly verify, and the TrustedValidators must -hash to TrustedConsensusState.NextValidatorsHash since that is the last -trusted validator set at the TrustedHeight. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `signed_header` | [tendermint.types.SignedHeader](#tendermint.types.SignedHeader) | | | -| `validator_set` | [tendermint.types.ValidatorSet](#tendermint.types.ValidatorSet) | | | -| `trusted_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `trusted_validators` | [tendermint.types.ValidatorSet](#tendermint.types.ValidatorSet) | | | + +

      Top

      +## ibc/lightclients/localhost/v1/localhost.proto - + -### Misbehaviour -Misbehaviour is a wrapper over two conflicting Headers -that implements Misbehaviour interface expected by ICS-02 +### ClientState +ClientState defines a loopback (localhost) client. It requires (read-only) +access to keys outside the client prefix. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `header_1` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | -| `header_2` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | +| `chain_id` | [string](#string) | | self chain ID | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | self latest block height | @@ -10643,6 +10525,128 @@ data sign byte encodings. + +

      Top

      + +## ibc/lightclients/tendermint/v1/tendermint.proto + + + + + +### ClientState +ClientState from Tendermint tracks the current validator set, latest height, +and a possible frozen height. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `chain_id` | [string](#string) | | | +| `trust_level` | [Fraction](#ibc.lightclients.tendermint.v1.Fraction) | | | +| `trusting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | duration of the period since the LastestTimestamp during which the submitted headers are valid for upgrade | +| `unbonding_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | duration of the staking unbonding period | +| `max_clock_drift` | [google.protobuf.Duration](#google.protobuf.Duration) | | defines how much new (untrusted) header's Time can drift into the future. | +| `frozen_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Block height when the client was frozen due to a misbehaviour | +| `latest_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Latest height the client was updated to | +| `proof_specs` | [ics23.ProofSpec](#ics23.ProofSpec) | repeated | Proof specifications used in verifying counterparty state | +| `upgrade_path` | [string](#string) | repeated | Path at which next upgraded client will be committed. Each element corresponds to the key for a single CommitmentProof in the chained proof. NOTE: ClientState must stored under `{upgradePath}/{upgradeHeight}/clientState` ConsensusState must be stored under `{upgradepath}/{upgradeHeight}/consensusState` For SDK chains using the default upgrade module, upgrade_path should be []string{"upgrade", "upgradedIBCState"}` | +| `allow_update_after_expiry` | [bool](#bool) | | This flag, when set to true, will allow governance to recover a client which has expired | +| `allow_update_after_misbehaviour` | [bool](#bool) | | This flag, when set to true, will allow governance to unfreeze a client whose chain has experienced a misbehaviour event | + + + + + + + + +### ConsensusState +ConsensusState defines the consensus state from Tendermint. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `timestamp` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | timestamp that corresponds to the block height in which the ConsensusState was stored. | +| `root` | [ibc.core.commitment.v1.MerkleRoot](#ibc.core.commitment.v1.MerkleRoot) | | commitment root (i.e app hash) | +| `next_validators_hash` | [bytes](#bytes) | | | + + + + + + + + +### Fraction +Fraction defines the protobuf message type for tmmath.Fraction that only supports positive values. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `numerator` | [uint64](#uint64) | | | +| `denominator` | [uint64](#uint64) | | | + + + + + + + + +### Header +Header defines the Tendermint client consensus Header. +It encapsulates all the information necessary to update from a trusted +Tendermint ConsensusState. The inclusion of TrustedHeight and +TrustedValidators allows this update to process correctly, so long as the +ConsensusState for the TrustedHeight exists, this removes race conditions +among relayers The SignedHeader and ValidatorSet are the new untrusted update +fields for the client. The TrustedHeight is the height of a stored +ConsensusState on the client that will be used to verify the new untrusted +header. The Trusted ConsensusState must be within the unbonding period of +current time in order to correctly verify, and the TrustedValidators must +hash to TrustedConsensusState.NextValidatorsHash since that is the last +trusted validator set at the TrustedHeight. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `signed_header` | [tendermint.types.SignedHeader](#tendermint.types.SignedHeader) | | | +| `validator_set` | [tendermint.types.ValidatorSet](#tendermint.types.ValidatorSet) | | | +| `trusted_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `trusted_validators` | [tendermint.types.ValidatorSet](#tendermint.types.ValidatorSet) | | | + + + + + + + + +### Misbehaviour +Misbehaviour is a wrapper over two conflicting Headers +that implements Misbehaviour interface expected by ICS-02 + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | | +| `header_1` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | +| `header_2` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | + + + + + + + + + + + + + + + ## Scalar Value Types | .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby | diff --git a/proto/cosmos/staking/v1beta1/staking.proto b/proto/cosmos/staking/v1beta1/staking.proto index eadc86e9d13a..e37b28b6d098 100644 --- a/proto/cosmos/staking/v1beta1/staking.proto +++ b/proto/cosmos/staking/v1beta1/staking.proto @@ -27,12 +27,15 @@ message CommissionRates { option (gogoproto.equal) = true; option (gogoproto.goproto_stringer) = false; + // rate is the commission rate charged to delegators, as a fraction. string rate = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; + // max_rate defines the maximum commission rate which validator can ever charge, as a fraction. string max_rate = 2 [ (gogoproto.moretags) = "yaml:\"max_rate\"", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; + // max_change_rate defines the maximum daily increase of the validator commission, as a fraction. string max_change_rate = 3 [ (gogoproto.moretags) = "yaml:\"max_change_rate\"", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", @@ -45,7 +48,9 @@ message Commission { option (gogoproto.equal) = true; option (gogoproto.goproto_stringer) = false; + // commission_rates defines the initial commission rates to be used for creating a validator. CommissionRates commission_rates = 1 [(gogoproto.embed) = true, (gogoproto.nullable) = false]; + // update_time is the last time the commission rate was changed. google.protobuf.Timestamp update_time = 2 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true, (gogoproto.moretags) = "yaml:\"update_time\""]; } @@ -55,10 +60,15 @@ message Description { option (gogoproto.equal) = true; option (gogoproto.goproto_stringer) = false; + // moniker defines a human-readable name for the validator. string moniker = 1; + // identity defines an optional identity signature (ex. UPort or Keybase). string identity = 2; + // website defines an optional website link. string website = 3; + // security_contact defines an optional email for security contact. string security_contact = 4 [(gogoproto.moretags) = "yaml:\"security_contact\""]; + // details define other optional details. string details = 5; } @@ -75,22 +85,33 @@ message Validator { option (gogoproto.goproto_stringer) = false; option (gogoproto.goproto_getters) = false; + // operator_address defines the address of the validator's operator; bech encoded in JSON. string operator_address = 1 [(gogoproto.moretags) = "yaml:\"operator_address\""]; + // consensus_pubkey is the consensus public key of the validator, as a Protobuf Any. google.protobuf.Any consensus_pubkey = 2 [(cosmos_proto.accepts_interface) = "cosmos.crypto.PubKey", (gogoproto.moretags) = "yaml:\"consensus_pubkey\""]; + // jailed defined whether the validator has been jailed from bonded status or not. bool jailed = 3; + // status is the validator status (bonded/unbonding/unbonded). BondStatus status = 4; + // tokens define the delegated tokens (incl. self-delegation). string tokens = 5 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false]; + // delegator_shares defines total shares issued to a validator's delegators. string delegator_shares = 6 [ (gogoproto.moretags) = "yaml:\"delegator_shares\"", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; + // description defines the description terms for the validator. Description description = 7 [(gogoproto.nullable) = false]; + // unbonding_height defines, if unbonding, the height at which this validator has begun unbonding. int64 unbonding_height = 8 [(gogoproto.moretags) = "yaml:\"unbonding_height\""]; + // unbonding_time defines, if unbonding, the min time for the validator to complete unbonding. google.protobuf.Timestamp unbonding_time = 9 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true, (gogoproto.moretags) = "yaml:\"unbonding_time\""]; + // commission defines the commission parameters. Commission commission = 10 [(gogoproto.nullable) = false]; + // min_self_delegation is the validator's self declared minimum self delegation. string min_self_delegation = 11 [ (gogoproto.moretags) = "yaml:\"min_self_delegation\"", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", @@ -164,8 +185,11 @@ message Delegation { option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_stringer) = false; + // delegator_address is the bech32-encoded address of the delegator. string delegator_address = 1 [(gogoproto.moretags) = "yaml:\"delegator_address\""]; + // validator_address is the bech32-encoded address of the validator. string validator_address = 2 [(gogoproto.moretags) = "yaml:\"validator_address\""]; + // shares define the delegation shares received. string shares = 3 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; } @@ -176,8 +200,11 @@ message UnbondingDelegation { option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_stringer) = false; + // delegator_address is the bech32-encoded address of the delegator. string delegator_address = 1 [(gogoproto.moretags) = "yaml:\"delegator_address\""]; + // validator_address is the bech32-encoded address of the validator. string validator_address = 2 [(gogoproto.moretags) = "yaml:\"validator_address\""]; + // entries are the unbonding delegation entries. repeated UnbondingDelegationEntry entries = 3 [(gogoproto.nullable) = false]; // unbonding delegation entries } @@ -186,14 +213,18 @@ message UnbondingDelegationEntry { option (gogoproto.equal) = true; option (gogoproto.goproto_stringer) = false; + // creation_height is the height which the unbonding took place. int64 creation_height = 1 [(gogoproto.moretags) = "yaml:\"creation_height\""]; + // completion_time is the unix time for unbonding completion. google.protobuf.Timestamp completion_time = 2 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true, (gogoproto.moretags) = "yaml:\"completion_time\""]; + // initial_balance defines the tokens initially scheduled to receive at completion. string initial_balance = 3 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"initial_balance\"" ]; + // balance defines the tokens to receive at completion. string balance = 4 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false]; } @@ -202,14 +233,18 @@ message RedelegationEntry { option (gogoproto.equal) = true; option (gogoproto.goproto_stringer) = false; + // creation_height defines the height which the redelegation took place. int64 creation_height = 1 [(gogoproto.moretags) = "yaml:\"creation_height\""]; + // completion_time defines the unix time for redelegation completion. google.protobuf.Timestamp completion_time = 2 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true, (gogoproto.moretags) = "yaml:\"completion_time\""]; + // initial_balance defines the initial balance when redelegation started. string initial_balance = 3 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"initial_balance\"" ]; + // shares_dst is the amount of destination-validator shares created by redelegation. string shares_dst = 4 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; } @@ -221,9 +256,13 @@ message Redelegation { option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_stringer) = false; + // delegator_address is the bech32-encoded address of the delegator. string delegator_address = 1 [(gogoproto.moretags) = "yaml:\"delegator_address\""]; + // validator_src_address is the validator redelegation source operator address. string validator_src_address = 2 [(gogoproto.moretags) = "yaml:\"validator_src_address\""]; + // validator_dst_address is the validator redelegation destination operator address. string validator_dst_address = 3 [(gogoproto.moretags) = "yaml:\"validator_dst_address\""]; + // entries are the redelegation entries. repeated RedelegationEntry entries = 4 [(gogoproto.nullable) = false]; // redelegation entries } @@ -232,11 +271,16 @@ message Params { option (gogoproto.equal) = true; option (gogoproto.goproto_stringer) = false; + // unbonding_time is the time duration of unbonding. google.protobuf.Duration unbonding_time = 1 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true, (gogoproto.moretags) = "yaml:\"unbonding_time\""]; + // max_validators is the maximum number of validators. uint32 max_validators = 2 [(gogoproto.moretags) = "yaml:\"max_validators\""]; + // max_entries is the max entries for either unbonding delegation or redelegation (per pair/trio). uint32 max_entries = 3 [(gogoproto.moretags) = "yaml:\"max_entries\""]; + // historical_entries is the number of historical entries to persist. uint32 historical_entries = 4 [(gogoproto.moretags) = "yaml:\"historical_entries\""]; + // bond_denom defines the bondable coin denomination. string bond_denom = 5 [(gogoproto.moretags) = "yaml:\"bond_denom\""]; } diff --git a/x/staking/spec/01_state.md b/x/staking/spec/01_state.md index c5f7376d7655..e090acb01541 100644 --- a/x/staking/spec/01_state.md +++ b/x/staking/spec/01_state.md @@ -8,23 +8,16 @@ order: 1 LastTotalPower tracks the total amounts of bonded tokens recorded during the previous end block. -- LastTotalPower: `0x12 -> amino(sdk.Int)` +- LastTotalPower: `0x12 -> ProtocolBuffer(sdk.Int)` ## Params Params is a module-wide configuration structure that stores system parameters and defines overall functioning of the staking module. -- Params: `Paramsspace("staking") -> amino(params)` +- Params: `Paramsspace("staking") -> legacy_amino(params)` -```go -type Params struct { - UnbondingTime time.Duration // time duration of unbonding - MaxValidators uint16 // maximum number of validators - MaxEntries uint16 // max entries for either unbonding delegation or redelegation (per pair/trio) - BondDenom string // bondable coin denomination -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.1/proto/cosmos/staking/v1beta1/staking.proto#L230-L241 ## Validator @@ -37,8 +30,8 @@ Validators can have one of three statuses They are signing blocks and receiving rewards. They can receive further delegations. They can be slashed for misbehavior. Delegators to this validator who unbond their delegation must wait the duration of the UnbondingTime, a chain-specific param. during which time - they are still slashable for offences of the source validator if those offences were committed - during the period of time that the tokens were bonded. + they are still slashable for offences of the source validator if those offences were committed + during the period of time that the tokens were bonded. - `Unbonding`: When a validator leaves the active set, either by choice or due to slashing or tombstoning, an unbonding of all their delegations begins. All delegations must then wait the UnbondingTime before moving receiving their tokens to their accounts from the `BondedPool`. @@ -51,10 +44,10 @@ required lookups for slashing and validator-set updates. A third special index throughout each block, unlike the first two indices which mirror the validator records within a block. -- Validators: `0x21 | OperatorAddr -> amino(validator)` +- Validators: `0x21 | OperatorAddr -> ProtocolBuffer(validator)` - ValidatorsByConsAddr: `0x22 | ConsAddr -> OperatorAddr` - ValidatorsByPower: `0x23 | BigEndian(ConsensusPower) | OperatorAddr -> OperatorAddr` -- LastValidatorsPower: `0x11 OperatorAddr -> amino(ConsensusPower)` +- LastValidatorsPower: `0x11 OperatorAddr -> ProtocolBuffer(ConsensusPower)` `Validators` is the primary index - it ensures that each operator can have only one associated validator, where the public key of that validator can change in the @@ -68,7 +61,7 @@ address which can be derived from the validator's `ConsPubKey`. `ValidatorsByPower` is an additional index that provides a sorted list o potential validators to quickly determine the current active set. Here -ConsensusPower is validator.Tokens/10^6. Note that all validators where +ConsensusPower is validator.Tokens/10^6. Note that all validators where `Jailed` is true are not stored within this index. `LastValidatorsPower` is a special index that provides a historical list of the @@ -77,60 +70,23 @@ is updated during the validator set update process which takes place in [`EndBlo Each validator's state is stored in a `Validator` struct: -```go -type Validator struct { - OperatorAddress sdk.ValAddress // address of the validator's operator; bech encoded in JSON - ConsPubKey crypto.PubKey // the consensus public key of the validator; bech encoded in JSON - Jailed bool // has the validator been jailed from bonded status? - Status sdk.BondStatus // validator status (bonded/unbonding/unbonded) - Tokens sdk.Int // delegated tokens (incl. self-delegation) - DelegatorShares sdk.Dec // total shares issued to a validator's delegators - Description Description // description terms for the validator - UnbondingHeight int64 // if unbonding, height at which this validator has begun unbonding - UnbondingCompletionTime time.Time // if unbonding, min time for the validator to complete unbonding - Commission Commission // commission parameters - MinSelfDelegation sdk.Int // validator's self declared minimum self delegation -} - -type Commission struct { - CommissionRates - UpdateTime time.Time // the last time the commission rate was changed -} - -CommissionRates struct { - Rate sdk.Dec // the commission rate charged to delegators, as a fraction - MaxRate sdk.Dec // maximum commission rate which validator can ever charge, as a fraction - MaxChangeRate sdk.Dec // maximum daily increase of the validator commission, as a fraction -} - -type Description struct { - Moniker string // name - Identity string // optional identity signature (ex. UPort or Keybase) - Website string // optional website link - SecurityContact string // optional email for security contact - Details string // optional details -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/staking.proto#L65-L99 + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/staking.proto#L24-L63 ## Delegation Delegations are identified by combining `DelegatorAddr` (the address of the delegator) with the `ValidatorAddr` Delegators are indexed in the store as follows: -- Delegation: `0x31 | DelegatorAddr | ValidatorAddr -> amino(delegation)` +- Delegation: `0x31 | DelegatorAddr | ValidatorAddr -> ProtocolBuffer(delegation)` Stake holders may delegate coins to validators; under this circumstance their funds are held in a `Delegation` data structure. It is owned by one delegator, and is associated with the shares for one validator. The sender of the transaction is the owner of the bond. -```go -type Delegation struct { - DelegatorAddr sdk.AccAddress - ValidatorAddr sdk.ValAddress - Shares sdk.Dec // delegation shares received -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/staking.proto#L159-L170 ### Delegator Shares @@ -159,10 +115,8 @@ detected. `UnbondingDelegation` are indexed in the store as: -- UnbondingDelegation: `0x32 | DelegatorAddr | ValidatorAddr -> - amino(unbondingDelegation)` -- UnbondingDelegationsFromValidator: `0x33 | ValidatorAddr | DelegatorAddr -> - nil` +- UnbondingDelegation: `0x32 | DelegatorAddr | ValidatorAddr -> ProtocolBuffer(unbondingDelegation)` +- UnbondingDelegationsFromValidator: `0x33 | ValidatorAddr | DelegatorAddr -> nil` The first map here is used in queries, to lookup all unbonding delegations for a given delegator, while the second map is used in slashing, to lookup all @@ -171,20 +125,7 @@ slashed. A UnbondingDelegation object is created every time an unbonding is initiated. -```go -type UnbondingDelegation struct { - DelegatorAddr sdk.AccAddress // delegator - ValidatorAddr sdk.ValAddress // validator unbonding from operator addr - Entries []UnbondingDelegationEntry // unbonding delegation entries -} - -type UnbondingDelegationEntry struct { - CreationHeight int64 // height which the unbonding took place - CompletionTime time.Time // unix time for unbonding completion - InitialBalance sdk.Coin // atoms initially scheduled to receive at completion - Balance sdk.Coin // atoms to receive at completion -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/staking.proto#L172-L198 ## Redelegation @@ -196,7 +137,7 @@ committed by the source validator. `Redelegation` are indexed in the store as: -- Redelegations: `0x34 | DelegatorAddr | ValidatorSrcAddr | ValidatorDstAddr -> amino(redelegation)` +- Redelegations: `0x34 | DelegatorAddr | ValidatorSrcAddr | ValidatorDstAddr -> ProtocolBuffer(redelegation)` - RedelegationsBySrc: `0x35 | ValidatorSrcAddr | ValidatorDstAddr | DelegatorAddr -> nil` - RedelegationsByDst: `0x36 | ValidatorDstAddr | ValidatorSrcAddr | DelegatorAddr -> nil` @@ -204,30 +145,15 @@ The first map here is used for queries, to lookup all redelegations for a given delegator. The second map is used for slashing based on the `ValidatorSrcAddr`, while the third map is for slashing based on the `ValidatorDstAddr`. -A redelegation object is created every time a redelegation occurs. To prevent +A redelegation object is created every time a redelegation occurs. To prevent "redelegation hopping" redelegations may not occur under the situation that: - the (re)delegator already has another immature redelegation in progress -with a destination to a validator (let's call it `Validator X`) + with a destination to a validator (let's call it `Validator X`) - and, the (re)delegator is attempting to create a _new_ redelegation -where the source validator for this new redelegation is `Validator-X`. - -```go -type Redelegation struct { - DelegatorAddr sdk.AccAddress // delegator - ValidatorSrcAddr sdk.ValAddress // validator redelegation source operator addr - ValidatorDstAddr sdk.ValAddress // validator redelegation destination operator addr - Entries []RedelegationEntry // redelegation entries -} - -type RedelegationEntry struct { - CreationHeight int64 // height which the redelegation took place - CompletionTime time.Time // unix time for redelegation completion - InitialBalance sdk.Coin // initial balance when redelegation started - Balance sdk.Coin // current balance (current value held in destination validator) - SharesDst sdk.Dec // amount of destination-validator shares created by redelegation -} -``` + where the source validator for this new redelegation is `Validator-X`. + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/staking.proto#L200-L228 ## Queues @@ -249,12 +175,7 @@ delegations queue is kept. - UnbondingDelegation: `0x41 | format(time) -> []DVPair` -```go -type DVPair struct { - DelegatorAddr sdk.AccAddress - ValidatorAddr sdk.ValAddress -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/staking.proto#L123-L133 ### RedelegationQueue @@ -263,13 +184,7 @@ kept. - UnbondingDelegation: `0x42 | format(time) -> []DVVTriplet` -```go -type DVVTriplet struct { - DelegatorAddr sdk.AccAddress - ValidatorSrcAddr sdk.ValAddress - ValidatorDstAddr sdk.ValAddress -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/staking.proto#L140-L152 ### ValidatorQueue @@ -279,7 +194,7 @@ queue is kept. - ValidatorQueueTime: `0x43 | format(time) -> []sdk.ValAddress` The stored object as each key is an array of validator operator addresses from -which the validator object can be accessed. Typically it is expected that only +which the validator object can be accessed. Typically it is expected that only a single validator record will be associated with a given timestamp however it is possible that multiple validators exist in the queue at the same location. @@ -288,15 +203,10 @@ that multiple validators exist in the queue at the same location. HistoricalInfo objects are stored and pruned at each block such that the staking keeper persists the `n` most recent historical info defined by staking module parameter: `HistoricalEntries`. -```go -type HistoricalInfo struct { - Header tmproto.Header - ValSet []types.Validator -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/staking.proto#L15-L22 At each BeginBlock, the staking keeper will persist the current Header and the Validators that committed -the current block in a `HistoricalInfo` object. The Validators are sorted on their address to ensure that +the current block in a `HistoricalInfo` object. The Validators are sorted on their address to ensure that they are in a determisnistic order. -The oldest HistoricalEntries will be pruned to ensure that there only exist the parameter-defined number of +The oldest HistoricalEntries will be pruned to ensure that there only exist the parameter-defined number of historical entries. diff --git a/x/staking/spec/02_state_transitions.md b/x/staking/spec/02_state_transitions.md index c2766aa43b79..9e245719cc24 100644 --- a/x/staking/spec/02_state_transitions.md +++ b/x/staking/spec/02_state_transitions.md @@ -11,12 +11,13 @@ This document describes the state transition operations pertaining to: 3. [Slashing](./02_state_transitions.md#slashing) ## Validators -State transitions in validators are performed on every [`EndBlock`](./05_end_block.md#validator-set-changes) + +State transitions in validators are performed on every [`EndBlock`](./05_end_block.md#validator-set-changes) in order to check for changes in the active `ValidatorSet`. ### Unbonded to Bonded -The following transition occurs when a validator's ranking in the `ValidatorPowerIndex` surpasses +The following transition occurs when a validator's ranking in the `ValidatorPowerIndex` surpasses that of the `LastValidator`. - set `validator.Status` to `Bonded` @@ -98,9 +99,9 @@ Redelegations affect the delegation, source and destination validators. - perform an `unbond` delegation from the source validator to retrieve the tokens worth of the unbonded shares - using the unbonded tokens, `Delegate` them to the destination validator -- if the `sourceValidator.Status` is `Bonded`, and the `destinationValidator` is not, +- if the `sourceValidator.Status` is `Bonded`, and the `destinationValidator` is not, transfer the newly delegated tokens from the `BondedPool` to the `NotBondedPool` `ModuleAccount` -- otherwise, if the `sourceValidator.Status` is not `Bonded`, and the `destinationValidator` +- otherwise, if the `sourceValidator.Status` is not `Bonded`, and the `destinationValidator` is `Bonded`, transfer the newly delegated tokens from the `NotBondedPool` to the `BondedPool` `ModuleAccount` - record the token amount in an new entry in the relevant `Redelegation` @@ -116,20 +117,20 @@ When a redelegations complete the following occurs: When a Validator is slashed, the following occurs: -- The total `slashAmount` is calculated as the `slashFactor` (a chain parameter) * `TokensFromConsensusPower`, -the total number of tokens bonded to the validator at the time of the infraction. +- The total `slashAmount` is calculated as the `slashFactor` (a chain parameter) \* `TokensFromConsensusPower`, + the total number of tokens bonded to the validator at the time of the infraction. - Every unbonding delegation and redelegation from the validator are slashed by the `slashFactor` -percentage of the initialBalance. + percentage of the initialBalance. - Each amount slashed from redelegations and unbonding delegations is subtracted from the -total slash amount. + total slash amount. - The `remaingSlashAmount` is then slashed from the validator's tokens in the `BondedPool` or -`NonBondedPool` depending on the validator's status. This reduces the total supply of tokens. + `NonBondedPool` depending on the validator's status. This reduces the total supply of tokens. ### Slash Unbonding Delegation -When a validator is slashed, so are those unbonding delegations from the validator that began unbonding -after the time of the infraction. Every entry in every unbonding delegation from the validator -is slashed by `slashFactor`. The amount slashed is calculated from the `InitialBalance` of the +When a validator is slashed, so are those unbonding delegations from the validator that began unbonding +after the time of the infraction. Every entry in every unbonding delegation from the validator +is slashed by `slashFactor`. The amount slashed is calculated from the `InitialBalance` of the delegation and is capped to prevent a resulting negative balance. Completed (or mature) unbondings are not slashed. ### Slash Redelegation diff --git a/x/staking/spec/03_messages.md b/x/staking/spec/03_messages.md index bd9f21e2ceb0..1155da93d97d 100644 --- a/x/staking/spec/03_messages.md +++ b/x/staking/spec/03_messages.md @@ -6,23 +6,15 @@ order: 3 In this section we describe the processing of the staking messages and the corresponding updates to the state. All created/modified state objects specified by each message are defined within the [state](./02_state_transitions.md) section. -## MsgCreateValidator +## Msg/CreateValidator -A validator is created using the `MsgCreateValidator` message. +A validator is created using the `Msg/CreateValidator` service message. -```go -type MsgCreateValidator struct { - Description Description - Commission Commission ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L16-L17 - DelegatorAddr sdk.AccAddress - ValidatorAddr sdk.ValAddress - PubKey crypto.PubKey - Delegation sdk.Coin -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L35-L51 -This message is expected to fail if: +This service message is expected to fail if: - another validator with this operator address is already registered - another validator with this pubkey is already registered @@ -33,71 +25,63 @@ This message is expected to fail if: - the initial `MaxChangeRate` is either negative or > `MaxRate` - the description fields are too large -This message creates and stores the `Validator` object at appropriate indexes. +This service message creates and stores the `Validator` object at appropriate indexes. Additionally a self-delegation is made with the initial tokens delegation tokens `Delegation`. The validator always starts as unbonded but may be bonded in the first end-block. -## MsgEditValidator +## Msg/EditValidator The `Description`, `CommissionRate` of a validator can be updated using the -`MsgEditCandidacy`. +`Msg/EditCandidacy` service message. -```go -type MsgEditCandidacy struct { - Description Description - ValidatorAddr sdk.ValAddress - CommissionRate sdk.Dec -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L19-L20 -This message is expected to fail if: ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L56-L76 + +This service message is expected to fail if: - the initial `CommissionRate` is either negative or > `MaxRate` - the `CommissionRate` has already been updated within the previous 24 hours - the `CommissionRate` is > `MaxChangeRate` - the description fields are too large -This message stores the updated `Validator` object. +This service message stores the updated `Validator` object. -## MsgDelegate +## Msg/Delegate -Within this message the delegator provides coins, and in return receives +Within this service message the delegator provides coins, and in return receives some amount of their validator's (newly created) delegator-shares that are assigned to `Delegation.Shares`. -```go -type MsgDelegate struct { - DelegatorAddr sdk.AccAddress - ValidatorAddr sdk.ValAddress - Amount sdk.Coin -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L22-L24 + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L81-L90 -This message is expected to fail if: +This service message is expected to fail if: - the validator is does not exist - the validator is jailed - the `Amount` `Coin` has a denomination different than one defined by `params.BondDenom` If an existing `Delegation` object for provided addresses does not already -exist than it is created as part of this message otherwise the existing +exist than it is created as part of this service message otherwise the existing `Delegation` is updated to include the newly received shares. -## MsgBeginUnbonding +## Msg/Undelegate -The begin unbonding message allows delegators to undelegate their tokens from +The `Msg/Undelegate` service message allows delegators to undelegate their tokens from validator. -```go -type MsgBeginUnbonding struct { - DelegatorAddr sdk.AccAddress - ValidatorAddr sdk.ValAddress - Amount sdk.Coin -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L30-L32 + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L112-L121 + +This service message returns a response containing the completion time of the undelegation: -This message is expected to fail if: ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L123-L126 + +This service message is expected to fail if: - the delegation doesn't exist - the validator doesn't exist @@ -105,7 +89,7 @@ This message is expected to fail if: - existing `UnbondingDelegation` has maximum entries as defined by `params.MaxEntries` - the `Amount` has a denomination different than one defined by `params.BondDenom` -When this message is processed the following actions occur: +When this service message is processed the following actions occur: - validator's `DelegatorShares` and the delegation's `Shares` are both reduced by the message `SharesAmount` - calculate the token worth of the shares remove that amount tokens held within the validator @@ -116,22 +100,21 @@ When this message is processed the following actions occur: - if there are no more `Shares` in the delegation, then the delegation object is removed from the store - under this situation if the delegation is the validator's self-delegation then also jail the validator. -## MsgBeginRedelegate +## Msg/BeginRedelegate The redelegation command allows delegators to instantly switch validators. Once the unbonding period has passed, the redelegation is automatically completed in the EndBlocker. -```go -type MsgBeginRedelegate struct { - DelegatorAddr sdk.AccAddress - ValidatorSrcAddr sdk.ValAddress - ValidatorDstAddr sdk.ValAddress - Amount sdk.Coin -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L26-L28 + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L95-L105 + +This service message returns a response containing the completion time of the redelegation: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L107-L110 -This message is expected to fail if: +This service message is expected to fail if: - the delegation doesn't exist - the source or destination validators don't exist @@ -140,7 +123,7 @@ This message is expected to fail if: - existing `Redelegation` has maximum entries as defined by `params.MaxEntries` - the `Amount` `Coin` has a denomination different than one defined by `params.BondDenom` -When this message is processed the following actions occur: +When this service message is processed the following actions occur: - the source validator's `DelegatorShares` and the delegations `Shares` are both reduced by the message `SharesAmount` - calculate the token worth of the shares remove that amount tokens held within the source validator. @@ -148,6 +131,6 @@ When this message is processed the following actions occur: - `Bonded` - add an entry to the `Redelegation` (create `Redelegation` if it doesn't exist) with a completion time a full unbonding period from the current time. Update pool shares to reduce BondedTokens and increase NotBondedTokens by token worth of the shares (this may be effectively reversed in the next step however). - `Unbonding` - add an entry to the `Redelegation` (create `Redelegation` if it doesn't exist) with the same completion time as the validator (`UnbondingMinTime`). - `Unbonded` - no action required in this step -- Delegate the token worth to the destination validator, possibly moving tokens back to the bonded state. +- Delegate the token worth to the destination validator, possibly moving tokens back to the bonded state. - if there are no more `Shares` in the source delegation, then the source delegation object is removed from the store - under this situation if the delegation is the validator's self-delegation then also jail the validator. diff --git a/x/staking/spec/07_events.md b/x/staking/spec/07_events.md index d8255ca92b13..660319b3c1a4 100644 --- a/x/staking/spec/07_events.md +++ b/x/staking/spec/07_events.md @@ -18,9 +18,9 @@ The staking module emits the following events: | complete_redelegation | destination_validator | {dstValidatorAddress} | | complete_redelegation | delegator | {delegatorAddress} | -## Handlers +## Service Messages -### MsgCreateValidator +### Msg/CreateValidator | Type | Attribute Key | Attribute Value | | ---------------- | ------------- | ------------------ | @@ -30,7 +30,7 @@ The staking module emits the following events: | message | action | create_validator | | message | sender | {senderAddress} | -### MsgEditValidator +### Msg/EditValidator | Type | Attribute Key | Attribute Value | | -------------- | ------------------- | ------------------- | @@ -40,7 +40,7 @@ The staking module emits the following events: | message | action | edit_validator | | message | sender | {senderAddress} | -### MsgDelegate +### Msg/Delegate | Type | Attribute Key | Attribute Value | | -------- | ------------- | ------------------ | @@ -50,7 +50,7 @@ The staking module emits the following events: | message | action | delegate | | message | sender | {senderAddress} | -### MsgUndelegate +### Msg/Undelegate | Type | Attribute Key | Attribute Value | | ------- | ------------------- | ------------------ | @@ -61,9 +61,9 @@ The staking module emits the following events: | message | action | begin_unbonding | | message | sender | {senderAddress} | -* [0] Time is formatted in the RFC3339 standard +- [0] Time is formatted in the RFC3339 standard -### MsgBeginRedelegate +### Msg/BeginRedelegate | Type | Attribute Key | Attribute Value | | ---------- | --------------------- | --------------------- | @@ -75,4 +75,4 @@ The staking module emits the following events: | message | action | begin_redelegate | | message | sender | {senderAddress} | -* [0] Time is formatted in the RFC3339 standard +- [0] Time is formatted in the RFC3339 standard diff --git a/x/staking/spec/README.md b/x/staking/spec/README.md index 0005088ae837..a2cb7cf3a8df 100644 --- a/x/staking/spec/README.md +++ b/x/staking/spec/README.md @@ -38,18 +38,18 @@ network. - [Delegations](02_state_transitions.md#delegations) - [Slashing](02_state_transitions.md#slashing) 3. **[Messages](03_messages.md)** - - [MsgCreateValidator](03_messages.md#msgcreatevalidator) - - [MsgEditValidator](03_messages.md#msgeditvalidator) - - [MsgDelegate](03_messages.md#msgdelegate) - - [MsgBeginUnbonding](03_messages.md#msgbeginunbonding) - - [MsgBeginRedelegate](03_messages.md#msgbeginredelegate) + - [Msg/CreateValidator](03_messages.md#msgcreatevalidator) + - [Msg/EditValidator](03_messages.md#msgeditvalidator) + - [Msg/Delegate](03_messages.md#msgdelegate) + - [Msg/BeginUnbonding](03_messages.md#msgbeginunbonding) + - [Msg/BeginRedelegate](03_messages.md#msgbeginredelegate) 4. **[Begin-Block](04_begin_block.md)** - [Historical Info Tracking](04_begin_block.md#historical-info-tracking) -4. **[End-Block ](05_end_block.md)** +5. **[End-Block ](05_end_block.md)** - [Validator Set Changes](05_end_block.md#validator-set-changes) - [Queues ](05_end_block.md#queues-) -5. **[Hooks](06_hooks.md)** -6. **[Events](07_events.md)** +6. **[Hooks](06_hooks.md)** +7. **[Events](07_events.md)** - [EndBlocker](07_events.md#endblocker) - [Handlers](07_events.md#handlers) -7. **[Parameters](08_params.md)** +8. **[Parameters](08_params.md)** diff --git a/x/staking/types/staking.pb.go b/x/staking/types/staking.pb.go index b97e1224c45a..45b30b7a0e5e 100644 --- a/x/staking/types/staking.pb.go +++ b/x/staking/types/staking.pb.go @@ -135,8 +135,11 @@ func (m *HistoricalInfo) GetValset() []Validator { // CommissionRates defines the initial commission rates to be used for creating // a validator. type CommissionRates struct { - Rate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,1,opt,name=rate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"rate"` - MaxRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=max_rate,json=maxRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"max_rate" yaml:"max_rate"` + // rate is the commission rate charged to delegators, as a fraction. + Rate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,1,opt,name=rate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"rate"` + // max_rate defines the maximum commission rate which validator can ever charge, as a fraction. + MaxRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=max_rate,json=maxRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"max_rate" yaml:"max_rate"` + // max_change_rate defines the maximum daily increase of the validator commission, as a fraction. MaxChangeRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=max_change_rate,json=maxChangeRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"max_change_rate" yaml:"max_change_rate"` } @@ -174,8 +177,10 @@ var xxx_messageInfo_CommissionRates proto.InternalMessageInfo // Commission defines commission parameters for a given validator. type Commission struct { + // commission_rates defines the initial commission rates to be used for creating a validator. CommissionRates `protobuf:"bytes,1,opt,name=commission_rates,json=commissionRates,proto3,embedded=commission_rates" json:"commission_rates"` - UpdateTime time.Time `protobuf:"bytes,2,opt,name=update_time,json=updateTime,proto3,stdtime" json:"update_time" yaml:"update_time"` + // update_time is the last time the commission rate was changed. + UpdateTime time.Time `protobuf:"bytes,2,opt,name=update_time,json=updateTime,proto3,stdtime" json:"update_time" yaml:"update_time"` } func (m *Commission) Reset() { *m = Commission{} } @@ -219,11 +224,16 @@ func (m *Commission) GetUpdateTime() time.Time { // Description defines a validator description. type Description struct { - Moniker string `protobuf:"bytes,1,opt,name=moniker,proto3" json:"moniker,omitempty"` - Identity string `protobuf:"bytes,2,opt,name=identity,proto3" json:"identity,omitempty"` - Website string `protobuf:"bytes,3,opt,name=website,proto3" json:"website,omitempty"` + // moniker defines a human-readable name for the validator. + Moniker string `protobuf:"bytes,1,opt,name=moniker,proto3" json:"moniker,omitempty"` + // identity defines an optional identity signature (ex. UPort or Keybase). + Identity string `protobuf:"bytes,2,opt,name=identity,proto3" json:"identity,omitempty"` + // website defines an optional website link. + Website string `protobuf:"bytes,3,opt,name=website,proto3" json:"website,omitempty"` + // security_contact defines an optional email for security contact. SecurityContact string `protobuf:"bytes,4,opt,name=security_contact,json=securityContact,proto3" json:"security_contact,omitempty" yaml:"security_contact"` - Details string `protobuf:"bytes,5,opt,name=details,proto3" json:"details,omitempty"` + // details define other optional details. + Details string `protobuf:"bytes,5,opt,name=details,proto3" json:"details,omitempty"` } func (m *Description) Reset() { *m = Description{} } @@ -302,16 +312,27 @@ func (m *Description) GetDetails() string { // exchange rate. Voting power can be calculated as total bonded shares // multiplied by exchange rate. type Validator struct { - OperatorAddress string `protobuf:"bytes,1,opt,name=operator_address,json=operatorAddress,proto3" json:"operator_address,omitempty" yaml:"operator_address"` - ConsensusPubkey *types1.Any `protobuf:"bytes,2,opt,name=consensus_pubkey,json=consensusPubkey,proto3" json:"consensus_pubkey,omitempty" yaml:"consensus_pubkey"` - Jailed bool `protobuf:"varint,3,opt,name=jailed,proto3" json:"jailed,omitempty"` - Status BondStatus `protobuf:"varint,4,opt,name=status,proto3,enum=cosmos.staking.v1beta1.BondStatus" json:"status,omitempty"` - Tokens github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,5,opt,name=tokens,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"tokens"` - DelegatorShares github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=delegator_shares,json=delegatorShares,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"delegator_shares" yaml:"delegator_shares"` - Description Description `protobuf:"bytes,7,opt,name=description,proto3" json:"description"` - UnbondingHeight int64 `protobuf:"varint,8,opt,name=unbonding_height,json=unbondingHeight,proto3" json:"unbonding_height,omitempty" yaml:"unbonding_height"` - UnbondingTime time.Time `protobuf:"bytes,9,opt,name=unbonding_time,json=unbondingTime,proto3,stdtime" json:"unbonding_time" yaml:"unbonding_time"` - Commission Commission `protobuf:"bytes,10,opt,name=commission,proto3" json:"commission"` + // operator_address defines the address of the validator's operator; bech encoded in JSON. + OperatorAddress string `protobuf:"bytes,1,opt,name=operator_address,json=operatorAddress,proto3" json:"operator_address,omitempty" yaml:"operator_address"` + // consensus_pubkey is the consensus public key of the validator, as a Protobuf Any. + ConsensusPubkey *types1.Any `protobuf:"bytes,2,opt,name=consensus_pubkey,json=consensusPubkey,proto3" json:"consensus_pubkey,omitempty" yaml:"consensus_pubkey"` + // jailed defined whether the validator has been jailed from bonded status or not. + Jailed bool `protobuf:"varint,3,opt,name=jailed,proto3" json:"jailed,omitempty"` + // status is the validator status (bonded/unbonding/unbonded). + Status BondStatus `protobuf:"varint,4,opt,name=status,proto3,enum=cosmos.staking.v1beta1.BondStatus" json:"status,omitempty"` + // tokens define the delegated tokens (incl. self-delegation). + Tokens github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,5,opt,name=tokens,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"tokens"` + // delegator_shares defines total shares issued to a validator's delegators. + DelegatorShares github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=delegator_shares,json=delegatorShares,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"delegator_shares" yaml:"delegator_shares"` + // description defines the description terms for the validator. + Description Description `protobuf:"bytes,7,opt,name=description,proto3" json:"description"` + // unbonding_height defines, if unbonding, the height at which this validator has begun unbonding. + UnbondingHeight int64 `protobuf:"varint,8,opt,name=unbonding_height,json=unbondingHeight,proto3" json:"unbonding_height,omitempty" yaml:"unbonding_height"` + // unbonding_time defines, if unbonding, the min time for the validator to complete unbonding. + UnbondingTime time.Time `protobuf:"bytes,9,opt,name=unbonding_time,json=unbondingTime,proto3,stdtime" json:"unbonding_time" yaml:"unbonding_time"` + // commission defines the commission parameters. + Commission Commission `protobuf:"bytes,10,opt,name=commission,proto3" json:"commission"` + // min_self_delegation is the validator's self declared minimum self delegation. MinSelfDelegation github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,11,opt,name=min_self_delegation,json=minSelfDelegation,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"min_self_delegation" yaml:"min_self_delegation"` } @@ -567,9 +588,12 @@ func (m *DVVTriplets) GetTriplets() []DVVTriplet { // owned by one delegator, and is associated with the voting power of one // validator. type Delegation struct { - DelegatorAddress string `protobuf:"bytes,1,opt,name=delegator_address,json=delegatorAddress,proto3" json:"delegator_address,omitempty" yaml:"delegator_address"` - ValidatorAddress string `protobuf:"bytes,2,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty" yaml:"validator_address"` - Shares github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=shares,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"shares"` + // delegator_address is the bech32-encoded address of the delegator. + DelegatorAddress string `protobuf:"bytes,1,opt,name=delegator_address,json=delegatorAddress,proto3" json:"delegator_address,omitempty" yaml:"delegator_address"` + // validator_address is the bech32-encoded address of the validator. + ValidatorAddress string `protobuf:"bytes,2,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty" yaml:"validator_address"` + // shares define the delegation shares received. + Shares github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=shares,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"shares"` } func (m *Delegation) Reset() { *m = Delegation{} } @@ -607,9 +631,12 @@ var xxx_messageInfo_Delegation proto.InternalMessageInfo // UnbondingDelegation stores all of a single delegator's unbonding bonds // for a single validator in an time-ordered list. type UnbondingDelegation struct { - DelegatorAddress string `protobuf:"bytes,1,opt,name=delegator_address,json=delegatorAddress,proto3" json:"delegator_address,omitempty" yaml:"delegator_address"` - ValidatorAddress string `protobuf:"bytes,2,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty" yaml:"validator_address"` - Entries []UnbondingDelegationEntry `protobuf:"bytes,3,rep,name=entries,proto3" json:"entries"` + // delegator_address is the bech32-encoded address of the delegator. + DelegatorAddress string `protobuf:"bytes,1,opt,name=delegator_address,json=delegatorAddress,proto3" json:"delegator_address,omitempty" yaml:"delegator_address"` + // validator_address is the bech32-encoded address of the validator. + ValidatorAddress string `protobuf:"bytes,2,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty" yaml:"validator_address"` + // entries are the unbonding delegation entries. + Entries []UnbondingDelegationEntry `protobuf:"bytes,3,rep,name=entries,proto3" json:"entries"` } func (m *UnbondingDelegation) Reset() { *m = UnbondingDelegation{} } @@ -646,10 +673,14 @@ var xxx_messageInfo_UnbondingDelegation proto.InternalMessageInfo // UnbondingDelegationEntry defines an unbonding object with relevant metadata. type UnbondingDelegationEntry struct { - CreationHeight int64 `protobuf:"varint,1,opt,name=creation_height,json=creationHeight,proto3" json:"creation_height,omitempty" yaml:"creation_height"` - CompletionTime time.Time `protobuf:"bytes,2,opt,name=completion_time,json=completionTime,proto3,stdtime" json:"completion_time" yaml:"completion_time"` + // creation_height is the height which the unbonding took place. + CreationHeight int64 `protobuf:"varint,1,opt,name=creation_height,json=creationHeight,proto3" json:"creation_height,omitempty" yaml:"creation_height"` + // completion_time is the unix time for unbonding completion. + CompletionTime time.Time `protobuf:"bytes,2,opt,name=completion_time,json=completionTime,proto3,stdtime" json:"completion_time" yaml:"completion_time"` + // initial_balance defines the tokens initially scheduled to receive at completion. InitialBalance github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,3,opt,name=initial_balance,json=initialBalance,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"initial_balance" yaml:"initial_balance"` - Balance github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,4,opt,name=balance,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"balance"` + // balance defines the tokens to receive at completion. + Balance github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,4,opt,name=balance,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"balance"` } func (m *UnbondingDelegationEntry) Reset() { *m = UnbondingDelegationEntry{} } @@ -700,10 +731,14 @@ func (m *UnbondingDelegationEntry) GetCompletionTime() time.Time { // RedelegationEntry defines a redelegation object with relevant metadata. type RedelegationEntry struct { - CreationHeight int64 `protobuf:"varint,1,opt,name=creation_height,json=creationHeight,proto3" json:"creation_height,omitempty" yaml:"creation_height"` - CompletionTime time.Time `protobuf:"bytes,2,opt,name=completion_time,json=completionTime,proto3,stdtime" json:"completion_time" yaml:"completion_time"` + // creation_height defines the height which the redelegation took place. + CreationHeight int64 `protobuf:"varint,1,opt,name=creation_height,json=creationHeight,proto3" json:"creation_height,omitempty" yaml:"creation_height"` + // completion_time defines the unix time for redelegation completion. + CompletionTime time.Time `protobuf:"bytes,2,opt,name=completion_time,json=completionTime,proto3,stdtime" json:"completion_time" yaml:"completion_time"` + // initial_balance defines the initial balance when redelegation started. InitialBalance github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,3,opt,name=initial_balance,json=initialBalance,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"initial_balance" yaml:"initial_balance"` - SharesDst github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=shares_dst,json=sharesDst,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"shares_dst"` + // shares_dst is the amount of destination-validator shares created by redelegation. + SharesDst github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=shares_dst,json=sharesDst,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"shares_dst"` } func (m *RedelegationEntry) Reset() { *m = RedelegationEntry{} } @@ -755,10 +790,14 @@ func (m *RedelegationEntry) GetCompletionTime() time.Time { // Redelegation contains the list of a particular delegator's redelegating bonds // from a particular source validator to a particular destination validator. type Redelegation struct { - DelegatorAddress string `protobuf:"bytes,1,opt,name=delegator_address,json=delegatorAddress,proto3" json:"delegator_address,omitempty" yaml:"delegator_address"` - ValidatorSrcAddress string `protobuf:"bytes,2,opt,name=validator_src_address,json=validatorSrcAddress,proto3" json:"validator_src_address,omitempty" yaml:"validator_src_address"` - ValidatorDstAddress string `protobuf:"bytes,3,opt,name=validator_dst_address,json=validatorDstAddress,proto3" json:"validator_dst_address,omitempty" yaml:"validator_dst_address"` - Entries []RedelegationEntry `protobuf:"bytes,4,rep,name=entries,proto3" json:"entries"` + // delegator_address is the bech32-encoded address of the delegator. + DelegatorAddress string `protobuf:"bytes,1,opt,name=delegator_address,json=delegatorAddress,proto3" json:"delegator_address,omitempty" yaml:"delegator_address"` + // validator_src_address is the validator redelegation source operator address. + ValidatorSrcAddress string `protobuf:"bytes,2,opt,name=validator_src_address,json=validatorSrcAddress,proto3" json:"validator_src_address,omitempty" yaml:"validator_src_address"` + // validator_dst_address is the validator redelegation destination operator address. + ValidatorDstAddress string `protobuf:"bytes,3,opt,name=validator_dst_address,json=validatorDstAddress,proto3" json:"validator_dst_address,omitempty" yaml:"validator_dst_address"` + // entries are the redelegation entries. + Entries []RedelegationEntry `protobuf:"bytes,4,rep,name=entries,proto3" json:"entries"` } func (m *Redelegation) Reset() { *m = Redelegation{} } @@ -795,11 +834,16 @@ var xxx_messageInfo_Redelegation proto.InternalMessageInfo // Params defines the parameters for the staking module. type Params struct { - UnbondingTime time.Duration `protobuf:"bytes,1,opt,name=unbonding_time,json=unbondingTime,proto3,stdduration" json:"unbonding_time" yaml:"unbonding_time"` - MaxValidators uint32 `protobuf:"varint,2,opt,name=max_validators,json=maxValidators,proto3" json:"max_validators,omitempty" yaml:"max_validators"` - MaxEntries uint32 `protobuf:"varint,3,opt,name=max_entries,json=maxEntries,proto3" json:"max_entries,omitempty" yaml:"max_entries"` - HistoricalEntries uint32 `protobuf:"varint,4,opt,name=historical_entries,json=historicalEntries,proto3" json:"historical_entries,omitempty" yaml:"historical_entries"` - BondDenom string `protobuf:"bytes,5,opt,name=bond_denom,json=bondDenom,proto3" json:"bond_denom,omitempty" yaml:"bond_denom"` + // unbonding_time is the time duration of unbonding. + UnbondingTime time.Duration `protobuf:"bytes,1,opt,name=unbonding_time,json=unbondingTime,proto3,stdduration" json:"unbonding_time" yaml:"unbonding_time"` + // max_validators is the maximum number of validators. + MaxValidators uint32 `protobuf:"varint,2,opt,name=max_validators,json=maxValidators,proto3" json:"max_validators,omitempty" yaml:"max_validators"` + // max_entries is the max entries for either unbonding delegation or redelegation (per pair/trio). + MaxEntries uint32 `protobuf:"varint,3,opt,name=max_entries,json=maxEntries,proto3" json:"max_entries,omitempty" yaml:"max_entries"` + // historical_entries is the number of historical entries to persist. + HistoricalEntries uint32 `protobuf:"varint,4,opt,name=historical_entries,json=historicalEntries,proto3" json:"historical_entries,omitempty" yaml:"historical_entries"` + // bond_denom defines the bondable coin denomination. + BondDenom string `protobuf:"bytes,5,opt,name=bond_denom,json=bondDenom,proto3" json:"bond_denom,omitempty" yaml:"bond_denom"` } func (m *Params) Reset() { *m = Params{} } From 17d7e9a8d51e11340aab1705a3d47b6f98abff6f Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 1 Feb 2021 14:01:53 +0100 Subject: [PATCH 092/152] Add packet_connection attribute to packet lifecycle methods (#8458) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add packet_connection attribute to packet lifecycle methods Added to: * SendPacket * ReceivePacket * WriteAcknowledgement * AcknowledgePacket * Add CHANGELOG * Update CHANGELOG.md Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> --- CHANGELOG.md | 1 + x/ibc/core/04-channel/keeper/packet.go | 12 ++++++++++++ x/ibc/core/04-channel/types/events.go | 1 + 3 files changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bcb99bd84c5..12f0ff2d30a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (x/ibc) [\#8458](https://github.com/cosmos/cosmos-sdk/pull/8458) Add `packet_connection` attribute to ibc events to enable relayer filtering * (x/bank) [\#8479](https://github.com/cosmos/cosmos-sdk/pull/8479) Adittional client denom metadata validation for `base` and `display` denoms. * (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks. * [\#8396](https://github.com/cosmos/cosmos-sdk/pull/8396) Add support for ARM platform diff --git a/x/ibc/core/04-channel/keeper/packet.go b/x/ibc/core/04-channel/keeper/packet.go index 9af59745d549..49b59733c5a3 100644 --- a/x/ibc/core/04-channel/keeper/packet.go +++ b/x/ibc/core/04-channel/keeper/packet.go @@ -129,6 +129,9 @@ func (k Keeper) SendPacket( sdk.NewAttribute(types.AttributeKeyDstPort, packet.GetDestPort()), sdk.NewAttribute(types.AttributeKeyDstChannel, packet.GetDestChannel()), sdk.NewAttribute(types.AttributeKeyChannelOrdering, channel.Ordering.String()), + // we only support 1-hop packets now, and that is the most important hop for a relayer + // (is it going to a chain I am connected to) + sdk.NewAttribute(types.AttributeKeyConnection, channel.ConnectionHops[0]), ), sdk.NewEvent( sdk.EventTypeMessage, @@ -289,6 +292,9 @@ func (k Keeper) RecvPacket( sdk.NewAttribute(types.AttributeKeyDstPort, packet.GetDestPort()), sdk.NewAttribute(types.AttributeKeyDstChannel, packet.GetDestChannel()), sdk.NewAttribute(types.AttributeKeyChannelOrdering, channel.Ordering.String()), + // we only support 1-hop packets now, and that is the most important hop for a relayer + // (is it going to a chain I am connected to) + sdk.NewAttribute(types.AttributeKeyConnection, channel.ConnectionHops[0]), ), sdk.NewEvent( sdk.EventTypeMessage, @@ -370,6 +376,9 @@ func (k Keeper) WriteAcknowledgement( sdk.NewAttribute(types.AttributeKeyDstPort, packet.GetDestPort()), sdk.NewAttribute(types.AttributeKeyDstChannel, packet.GetDestChannel()), sdk.NewAttribute(types.AttributeKeyAck, string(acknowledgement)), + // we only support 1-hop packets now, and that is the most important hop for a relayer + // (is it going to a chain I am connected to) + sdk.NewAttribute(types.AttributeKeyConnection, channel.ConnectionHops[0]), ), sdk.NewEvent( sdk.EventTypeMessage, @@ -505,6 +514,9 @@ func (k Keeper) AcknowledgePacket( sdk.NewAttribute(types.AttributeKeyDstPort, packet.GetDestPort()), sdk.NewAttribute(types.AttributeKeyDstChannel, packet.GetDestChannel()), sdk.NewAttribute(types.AttributeKeyChannelOrdering, channel.Ordering.String()), + // we only support 1-hop packets now, and that is the most important hop for a relayer + // (is it going to a chain I am connected to) + sdk.NewAttribute(types.AttributeKeyConnection, channel.ConnectionHops[0]), ), sdk.NewEvent( sdk.EventTypeMessage, diff --git a/x/ibc/core/04-channel/types/events.go b/x/ibc/core/04-channel/types/events.go index 923587d439d7..b9ddb3052c30 100644 --- a/x/ibc/core/04-channel/types/events.go +++ b/x/ibc/core/04-channel/types/events.go @@ -30,6 +30,7 @@ const ( AttributeKeyDstPort = "packet_dst_port" AttributeKeyDstChannel = "packet_dst_channel" AttributeKeyChannelOrdering = "packet_channel_ordering" + AttributeKeyConnection = "packet_connection" ) // IBC channel events vars From c1b567f44c093ae68c551dc88b0e4886a187c213 Mon Sep 17 00:00:00 2001 From: Amaury Date: Mon, 1 Feb 2021 14:17:44 +0100 Subject: [PATCH 093/152] Refactor store keys for variable-length addresses (#8363) * Change account store key in x/bank * Fix pagination test * Fix merge master * Fix staking keys.go * Use bech32 in val state change map * Fix sortNoLongerBonded * Use length-prefix function * Use length prefix function * Fix test accountStore * Fix ExamplePaginate * Fix staking keys * Use shorter balances prefix * Do slashing keys * Fix gov keys * Fix x/gov tests * Fix x/distrib * Address reviews * add change log entry * Add changelog * Fix failing tests * Fix sim tests * fix after-export sim * Fix lint * Address review * Fix x/authz * Fix global config in test * Update x/staking/keeper/val_state_change.go Co-authored-by: Robert Zaremba * Address comments * Fix comments * Address review * Fix authz test * Update comment * Rename to LengthPrefixedAddressStoreKey * Use variable * Rename function * Fix test build * chore: update rosetta CI (#8453) * Rename again * Rename yet again * Update feegrant keys * Add function to create prefix Co-authored-by: Robert Zaremba Co-authored-by: Frojdi Dymylja <33157909+fdymylja@users.noreply.github.com> Co-authored-by: Aaron Craelius Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- CHANGELOG.md | 5 + contrib/rosetta/configuration/bootstrap.json | 4 +- contrib/rosetta/configuration/data.sh | 5 +- contrib/rosetta/configuration/staking.ros | 4 +- contrib/rosetta/node/data.tar.gz | Bin 34626 -> 36558 bytes simapp/export.go | 2 +- types/address.go | 14 +- types/address/store_key.go | 33 ++++ types/address/store_key_test.go | 38 +++++ types/address_test.go | 40 +++-- types/query/filtered_pagination_test.go | 5 +- types/query/pagination_test.go | 3 +- x/authz/types/keys.go | 19 ++- x/bank/keeper/grpc_query.go | 4 +- x/bank/keeper/send.go | 9 +- x/bank/keeper/view.go | 15 +- x/bank/types/key.go | 18 ++- x/bank/types/key_test.go | 5 +- x/bank/types/msgs_test.go | 21 ++- x/distribution/types/keys.go | 143 +++++++++-------- x/feegrant/types/key.go | 5 +- x/gov/types/keys.go | 17 +- x/gov/types/keys_test.go | 10 -- x/slashing/types/keys.go | 23 +-- x/staking/keeper/val_state_change.go | 63 +++++--- x/staking/keeper/validator.go | 2 +- x/staking/types/keys.go | 155 ++++++++++--------- x/staking/types/keys_test.go | 20 +-- 28 files changed, 411 insertions(+), 271 deletions(-) create mode 100644 types/address/store_key.go create mode 100644 types/address/store_key_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 12f0ff2d30a1..1a5fa83652ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,8 +36,13 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### Client Breaking Changes + +* [\#8363](https://github.com/cosmos/cosmos-sdk/issues/8363) Addresses no longer have a fixed 20-byte length. From the SDK modules' point of view, any 1-255 bytes-long byte array is a valid address. + ### State Machine Breaking +* (x/{bank,distrib,gov,slashing,staking}) [\#8363](https://github.com/cosmos/cosmos-sdk/issues/8363) Store keys have been modified to allow for variable-length addresses. * (x/ibc) [\#8266](https://github.com/cosmos/cosmos-sdk/issues/8266) Add amino JSON for IBC messages in order to support Ledger text signing. ### Improvements diff --git a/contrib/rosetta/configuration/bootstrap.json b/contrib/rosetta/configuration/bootstrap.json index 15b75b550862..1793988f37e5 100644 --- a/contrib/rosetta/configuration/bootstrap.json +++ b/contrib/rosetta/configuration/bootstrap.json @@ -1,12 +1,12 @@ [ { "account_identifier": { - "address":"cosmos1hdmjfmqmf8ck4pv4evu0s3up0ucm0yjjqfl87e" + "address":"cosmos158nkd0l9tyemv2crp579rmj8dg37qty8lzff88" }, "currency":{ "symbol":"stake", "decimals":0 }, - "value": "999900000000" + "value": "999990000000" } ] \ No newline at end of file diff --git a/contrib/rosetta/configuration/data.sh b/contrib/rosetta/configuration/data.sh index dc4f2cb59a86..45297d5a21bf 100644 --- a/contrib/rosetta/configuration/data.sh +++ b/contrib/rosetta/configuration/data.sh @@ -16,12 +16,13 @@ simd init simd --chain-id testing simd keys add fd --keyring-backend=test addr=$(simd keys show fd -a --keyring-backend=test) +val_addr=$(simd keys show fd --keyring-backend=test --bech val -a) # give the accounts some money simd add-genesis-account "$addr" 1000000000000stake --keyring-backend=test # save configs for the daemon -simd gentx fd --chain-id testing --keyring-backend=test +simd gentx fd 10000000stake --chain-id testing --keyring-backend=test # input genTx to the genesis file simd collect-gentxs @@ -55,4 +56,4 @@ echo zipping data dir and saving to /tmp/data.tar.gz tar -czvf /tmp/data.tar.gz /root/.simapp -echo new address for bootstrap.json "$addr" +echo new address for bootstrap.json "$addr" "$val_addr" diff --git a/contrib/rosetta/configuration/staking.ros b/contrib/rosetta/configuration/staking.ros index 1d9de1d180fa..4f89a43b9893 100644 --- a/contrib/rosetta/configuration/staking.ros +++ b/contrib/rosetta/configuration/staking.ros @@ -94,7 +94,7 @@ staking(1){ "account": { "address": "staking_account", "sub_account": { - "address" : "cosmosvaloper1hdmjfmqmf8ck4pv4evu0s3up0ucm0yjj9atjj2" + "address" : "cosmosvaloper158nkd0l9tyemv2crp579rmj8dg37qty86kaut5" } }, "amount":{ @@ -134,7 +134,7 @@ staking(1){ "account": { "address": "staking_account", "sub_account": { - "address" : "cosmosvaloper1hdmjfmqmf8ck4pv4evu0s3up0ucm0yjj9atjj2" + "address" : "cosmosvaloper158nkd0l9tyemv2crp579rmj8dg37qty86kaut5" } }, "amount":{ diff --git a/contrib/rosetta/node/data.tar.gz b/contrib/rosetta/node/data.tar.gz index a7bed60579ea098baa390af3a29e05b08d16dcc8..ad285ac62e75198c4945859e12ccf7b563c7c29b 100644 GIT binary patch literal 36558 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 W{ds@hpZDkg{P{11*Qv_@PyztMa6X;@ literal 34626 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 O?DZF9r!))zMgjoC3=_)$ diff --git a/simapp/export.go b/simapp/export.go index 887308d30a94..8d09e333a2e1 100644 --- a/simapp/export.go +++ b/simapp/export.go @@ -157,7 +157,7 @@ func (app *SimApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs [] counter := int16(0) for ; iter.Valid(); iter.Next() { - addr := sdk.ValAddress(iter.Key()[1:]) + addr := sdk.ValAddress(stakingtypes.AddressFromValidatorsKey(iter.Key())) validator, found := app.StakingKeeper.GetValidator(ctx, addr) if !found { panic("expected validator, not found") diff --git a/types/address.go b/types/address.go index ba9e5b303b6a..eabff6fa97ee 100644 --- a/types/address.go +++ b/types/address.go @@ -12,7 +12,9 @@ import ( "github.com/cosmos/cosmos-sdk/codec/legacy" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/types/address" "github.com/cosmos/cosmos-sdk/types/bech32" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) const ( @@ -28,8 +30,6 @@ const ( // config.SetFullFundraiserPath(yourFullFundraiserPath) // config.Seal() - // AddrLen defines a valid address length - AddrLen = 20 // Bech32MainPrefix defines the main SDK Bech32 prefix of an account's address Bech32MainPrefix = "cosmos" @@ -110,9 +110,15 @@ func VerifyAddressFormat(bz []byte) error { if verifier != nil { return verifier(bz) } - if len(bz) != AddrLen { - return fmt.Errorf("incorrect address length (expected: %d, actual: %d)", AddrLen, len(bz)) + + if len(bz) == 0 { + return sdkerrors.Wrap(sdkerrors.ErrUnknownAddress, "addresses cannot be empty") + } + + if len(bz) > address.MaxAddrLen { + return sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "address max length is %d, got %d", address.MaxAddrLen, len(bz)) } + return nil } diff --git a/types/address/store_key.go b/types/address/store_key.go new file mode 100644 index 000000000000..948491972936 --- /dev/null +++ b/types/address/store_key.go @@ -0,0 +1,33 @@ +package address + +import ( + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// MaxAddrLen is the maximum allowed length (in bytes) for an address. +const MaxAddrLen = 255 + +// LengthPrefix prefixes the address bytes with its length, this is used +// for example for variable-length components in store keys. +func LengthPrefix(bz []byte) ([]byte, error) { + bzLen := len(bz) + if bzLen == 0 { + return bz, nil + } + + if bzLen > MaxAddrLen { + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "address length should be max %d bytes, got %d", MaxAddrLen, bzLen) + } + + return append([]byte{byte(bzLen)}, bz...), nil +} + +// MustLengthPrefix is LengthPrefix with panic on error. +func MustLengthPrefix(bz []byte) []byte { + res, err := LengthPrefix(bz) + if err != nil { + panic(err) + } + + return res +} diff --git a/types/address/store_key_test.go b/types/address/store_key_test.go new file mode 100644 index 000000000000..3bb00bd022b0 --- /dev/null +++ b/types/address/store_key_test.go @@ -0,0 +1,38 @@ +package address_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/types/address" +) + +func TestLengthPrefixedAddressStoreKey(t *testing.T) { + addr10byte := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} + addr20byte := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19} + addr256byte := make([]byte, 256) + + tests := []struct { + name string + addr []byte + expStoreKey []byte + expErr bool + }{ + {"10-byte address", addr10byte, append([]byte{byte(10)}, addr10byte...), false}, + {"20-byte address", addr20byte, append([]byte{byte(20)}, addr20byte...), false}, + {"256-byte address (too long)", addr256byte, nil, true}, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + storeKey, err := address.LengthPrefix(tt.addr) + if tt.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tt.expStoreKey, storeKey) + } + }) + } +} diff --git a/types/address_test.go b/types/address_test.go index 5796c891acb0..b9bc0c3c5308 100644 --- a/types/address_test.go +++ b/types/address_test.go @@ -347,15 +347,18 @@ func (s *addressTestSuite) TestVerifyAddressFormat() { addr5 := make([]byte, 5) addr20 := make([]byte, 20) addr32 := make([]byte, 32) + addr256 := make([]byte, 256) err := types.VerifyAddressFormat(addr0) - s.Require().EqualError(err, "incorrect address length 0") + s.Require().EqualError(err, "addresses cannot be empty: unknown address") err = types.VerifyAddressFormat(addr5) - s.Require().EqualError(err, "incorrect address length 5") + s.Require().NoError(err) err = types.VerifyAddressFormat(addr20) - s.Require().Nil(err) + s.Require().NoError(err) err = types.VerifyAddressFormat(addr32) - s.Require().EqualError(err, "incorrect address length 32") + s.Require().NoError(err) + err = types.VerifyAddressFormat(addr256) + s.Require().EqualError(err, "address max length is 255, got 256: unknown address") } func (s *addressTestSuite) TestCustomAddressVerifier() { @@ -364,34 +367,39 @@ func (s *addressTestSuite) TestCustomAddressVerifier() { accBech := types.AccAddress(addr).String() valBech := types.ValAddress(addr).String() consBech := types.ConsAddress(addr).String() - // Verifiy that the default logic rejects this 10 byte address + // Verify that the default logic doesn't reject this 10 byte address + // The default verifier is nil, we're only checking address length is + // between 1-255 bytes. err := types.VerifyAddressFormat(addr) - s.Require().NotNil(err) + s.Require().Nil(err) _, err = types.AccAddressFromBech32(accBech) - s.Require().NotNil(err) + s.Require().Nil(err) _, err = types.ValAddressFromBech32(valBech) - s.Require().NotNil(err) + s.Require().Nil(err) _, err = types.ConsAddressFromBech32(consBech) - s.Require().NotNil(err) + s.Require().Nil(err) - // Set a custom address verifier that accepts 10 or 20 byte addresses + // Set a custom address verifier only accepts 20 byte addresses types.GetConfig().SetAddressVerifier(func(bz []byte) error { n := len(bz) - if n == 10 || n == types.AddrLen { + if n == 20 { return nil } return fmt.Errorf("incorrect address length %d", n) }) - // Verifiy that the custom logic accepts this 10 byte address + // Verifiy that the custom logic rejects this 10 byte address err = types.VerifyAddressFormat(addr) - s.Require().Nil(err) + s.Require().NotNil(err) _, err = types.AccAddressFromBech32(accBech) - s.Require().Nil(err) + s.Require().NotNil(err) _, err = types.ValAddressFromBech32(valBech) - s.Require().Nil(err) + s.Require().NotNil(err) _, err = types.ConsAddressFromBech32(consBech) - s.Require().Nil(err) + s.Require().NotNil(err) + + // Reinitialize the global config to default address verifier (nil) + types.GetConfig().SetAddressVerifier(nil) } func (s *addressTestSuite) TestBech32ifyAddressBytes() { diff --git a/types/query/filtered_pagination_test.go b/types/query/filtered_pagination_test.go index dbd2057da473..2622f7b8e7c8 100644 --- a/types/query/filtered_pagination_test.go +++ b/types/query/filtered_pagination_test.go @@ -6,6 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" "github.com/cosmos/cosmos-sdk/types/query" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -111,7 +112,7 @@ func ExampleFilteredPaginate() { pageReq := &query.PageRequest{Key: nil, Limit: 1, CountTotal: true} store := ctx.KVStore(app.GetKey(authtypes.StoreKey)) balancesStore := prefix.NewStore(store, types.BalancesPrefix) - accountStore := prefix.NewStore(balancesStore, addr1.Bytes()) + accountStore := prefix.NewStore(balancesStore, address.MustLengthPrefix(addr1)) var balResult sdk.Coins pageRes, err := query.FilteredPaginate(accountStore, pageReq, func(key []byte, value []byte, accumulate bool) (bool, error) { @@ -143,7 +144,7 @@ func ExampleFilteredPaginate() { func execFilterPaginate(store sdk.KVStore, pageReq *query.PageRequest, appCodec codec.Marshaler) (balances sdk.Coins, res *query.PageResponse, err error) { balancesStore := prefix.NewStore(store, types.BalancesPrefix) - accountStore := prefix.NewStore(balancesStore, addr1.Bytes()) + accountStore := prefix.NewStore(balancesStore, address.MustLengthPrefix(addr1)) var balResult sdk.Coins res, err = query.FilteredPaginate(accountStore, pageReq, func(key []byte, value []byte, accumulate bool) (bool, error) { diff --git a/types/query/pagination_test.go b/types/query/pagination_test.go index f0e1377a1e91..18853e97cc69 100644 --- a/types/query/pagination_test.go +++ b/types/query/pagination_test.go @@ -17,6 +17,7 @@ import ( "github.com/cosmos/cosmos-sdk/store" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" "github.com/cosmos/cosmos-sdk/types/query" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -193,7 +194,7 @@ func ExamplePaginate() { balResult := sdk.NewCoins() authStore := ctx.KVStore(app.GetKey(authtypes.StoreKey)) balancesStore := prefix.NewStore(authStore, types.BalancesPrefix) - accountStore := prefix.NewStore(balancesStore, addr1.Bytes()) + accountStore := prefix.NewStore(balancesStore, address.MustLengthPrefix(addr1)) pageRes, err := query.Paginate(accountStore, request.Pagination, func(key []byte, value []byte) error { var tempRes sdk.Coin err := app.AppCodec().UnmarshalBinaryBare(value, &tempRes) diff --git a/x/authz/types/keys.go b/x/authz/types/keys.go index 3be659c5aeb8..7ee571b27f74 100644 --- a/x/authz/types/keys.go +++ b/x/authz/types/keys.go @@ -2,6 +2,7 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" ) const ( @@ -21,7 +22,7 @@ const ( // Keys for authz store // Items are stored with the following key: values // -// - 0x01: Grant +// - 0x01: Grant var ( // Keys for store prefixes @@ -30,12 +31,22 @@ var ( // GetAuthorizationStoreKey - return authorization store key func GetAuthorizationStoreKey(grantee sdk.AccAddress, granter sdk.AccAddress, msgType string) []byte { - return append(append(append(GrantKey, granter.Bytes()...), grantee.Bytes()...), []byte(msgType)...) + return append(append(append( + GrantKey, + address.MustLengthPrefix(granter)...), + address.MustLengthPrefix(grantee)...), + []byte(msgType)..., + ) } // ExtractAddressesFromGrantKey - split granter & grantee address from the authorization key func ExtractAddressesFromGrantKey(key []byte) (granterAddr, granteeAddr sdk.AccAddress) { - granterAddr = sdk.AccAddress(key[1 : sdk.AddrLen+1]) - granteeAddr = sdk.AccAddress(key[sdk.AddrLen+1 : sdk.AddrLen*2+1]) + // key if of format: + // 0x01 + granterAddrLen := key[1] // remove prefix key + granterAddr = sdk.AccAddress(key[2 : 2+granterAddrLen]) + granteeAddrLen := int(key[2+granterAddrLen]) + granteeAddr = sdk.AccAddress(key[3+granterAddrLen : 3+granterAddrLen+byte(granteeAddrLen)]) + return granterAddr, granteeAddr } diff --git a/x/bank/keeper/grpc_query.go b/x/bank/keeper/grpc_query.go index ae00d1b8734a..b8f69ef1275b 100644 --- a/x/bank/keeper/grpc_query.go +++ b/x/bank/keeper/grpc_query.go @@ -57,9 +57,7 @@ func (k BaseKeeper) AllBalances(ctx context.Context, req *types.QueryAllBalances sdkCtx := sdk.UnwrapSDKContext(ctx) balances := sdk.NewCoins() - store := sdkCtx.KVStore(k.storeKey) - balancesStore := prefix.NewStore(store, types.BalancesPrefix) - accountStore := prefix.NewStore(balancesStore, addr.Bytes()) + accountStore := k.getAccountStore(sdkCtx, addr) pageRes, err := query.Paginate(accountStore, req.Pagination, func(_, value []byte) error { var result sdk.Coin diff --git a/x/bank/keeper/send.go b/x/bank/keeper/send.go index c1000b7d3025..694c43211e07 100644 --- a/x/bank/keeper/send.go +++ b/x/bank/keeper/send.go @@ -2,7 +2,6 @@ package keeper import ( "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/store/prefix" "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -233,9 +232,7 @@ func (k BaseSendKeeper) ClearBalances(ctx sdk.Context, addr sdk.AccAddress) { return false }) - store := ctx.KVStore(k.storeKey) - balancesStore := prefix.NewStore(store, types.BalancesPrefix) - accountStore := prefix.NewStore(balancesStore, addr.Bytes()) + accountStore := k.getAccountStore(ctx, addr) for _, key := range keys { accountStore.Delete(key) @@ -264,9 +261,7 @@ func (k BaseSendKeeper) SetBalance(ctx sdk.Context, addr sdk.AccAddress, balance return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, balance.String()) } - store := ctx.KVStore(k.storeKey) - balancesStore := prefix.NewStore(store, types.BalancesPrefix) - accountStore := prefix.NewStore(balancesStore, addr.Bytes()) + accountStore := k.getAccountStore(ctx, addr) bz := k.cdc.MustMarshalBinaryBare(&balance) accountStore.Set([]byte(balance.Denom), bz) diff --git a/x/bank/keeper/view.go b/x/bank/keeper/view.go index d4bcabad2b62..1b50fb81d3aa 100644 --- a/x/bank/keeper/view.go +++ b/x/bank/keeper/view.go @@ -97,9 +97,7 @@ func (k BaseViewKeeper) GetAccountsBalances(ctx sdk.Context) []types.Balance { // GetBalance returns the balance of a specific denomination for a given account // by address. func (k BaseViewKeeper) GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { - store := ctx.KVStore(k.storeKey) - balancesStore := prefix.NewStore(store, types.BalancesPrefix) - accountStore := prefix.NewStore(balancesStore, addr.Bytes()) + accountStore := k.getAccountStore(ctx, addr) bz := accountStore.Get([]byte(denom)) if bz == nil { @@ -116,9 +114,7 @@ func (k BaseViewKeeper) GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom s // provides the token balance to a callback. If true is returned from the // callback, iteration is halted. func (k BaseViewKeeper) IterateAccountBalances(ctx sdk.Context, addr sdk.AccAddress, cb func(sdk.Coin) bool) { - store := ctx.KVStore(k.storeKey) - balancesStore := prefix.NewStore(store, types.BalancesPrefix) - accountStore := prefix.NewStore(balancesStore, addr.Bytes()) + accountStore := k.getAccountStore(ctx, addr) iterator := accountStore.Iterator(nil, nil) defer iterator.Close() @@ -214,3 +210,10 @@ func (k BaseViewKeeper) ValidateBalance(ctx sdk.Context, addr sdk.AccAddress) er return nil } + +// getAccountStore gets the account store of the given address. +func (k BaseViewKeeper) getAccountStore(ctx sdk.Context, addr sdk.AccAddress) prefix.Store { + store := ctx.KVStore(k.storeKey) + + return prefix.NewStore(store, types.CreateAccountBalancesPrefix(addr)) +} diff --git a/x/bank/types/key.go b/x/bank/types/key.go index ec8619d00185..858fd2480ac9 100644 --- a/x/bank/types/key.go +++ b/x/bank/types/key.go @@ -1,9 +1,8 @@ package types import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" ) const ( @@ -22,7 +21,9 @@ const ( // KVStore keys var ( - BalancesPrefix = []byte("balances") + // BalancesPrefix is the for the account balances store. We use a byte + // (instead of say `[]]byte("balances")` to save some disk space). + BalancesPrefix = []byte{0x02} SupplyKey = []byte{0x00} DenomMetadataPrefix = []byte{0x1} ) @@ -37,10 +38,13 @@ func DenomMetadataKey(denom string) []byte { // store. The key must not contain the perfix BalancesPrefix as the prefix store // iterator discards the actual prefix. func AddressFromBalancesStore(key []byte) sdk.AccAddress { - addr := key[:sdk.AddrLen] - if len(addr) != sdk.AddrLen { - panic(fmt.Sprintf("unexpected account address key length; got: %d, expected: %d", len(addr), sdk.AddrLen)) - } + addrLen := key[0] + addr := key[1 : addrLen+1] return sdk.AccAddress(addr) } + +// CreateAccountBalancesPrefix creates the prefix for an account's balances. +func CreateAccountBalancesPrefix(addr []byte) []byte { + return append(BalancesPrefix, address.MustLengthPrefix(addr)...) +} diff --git a/x/bank/types/key_test.go b/x/bank/types/key_test.go index f3b5717fbecb..206ef8335c91 100644 --- a/x/bank/types/key_test.go +++ b/x/bank/types/key_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/require" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -19,8 +20,10 @@ func cloneAppend(bz []byte, tail []byte) (res []byte) { func TestAddressFromBalancesStore(t *testing.T) { addr, err := sdk.AccAddressFromBech32("cosmos1n88uc38xhjgxzw9nwre4ep2c8ga4fjxcar6mn7") require.NoError(t, err) + addrLen := len(addr) + require.Equal(t, 20, addrLen) - key := cloneAppend(addr.Bytes(), []byte("stake")) + key := cloneAppend(address.MustLengthPrefix(addr), []byte("stake")) res := types.AddressFromBalancesStore(key) require.Equal(t, res, addr) } diff --git a/x/bank/types/msgs_test.go b/x/bank/types/msgs_test.go index 96132150ad4f..334d72c13243 100644 --- a/x/bank/types/msgs_test.go +++ b/x/bank/types/msgs_test.go @@ -23,7 +23,7 @@ func TestMsgSendValidation(t *testing.T) { addr1 := sdk.AccAddress([]byte("from________________")) addr2 := sdk.AccAddress([]byte("to__________________")) addrEmpty := sdk.AccAddress([]byte("")) - addrTooLong := sdk.AccAddress([]byte("Accidentally used 33 bytes pubkey")) + addrLong := sdk.AccAddress([]byte("Purposefully long address")) atom123 := sdk.NewCoins(sdk.NewInt64Coin("atom", 123)) atom0 := sdk.NewCoins(sdk.NewInt64Coin("atom", 0)) @@ -36,12 +36,12 @@ func TestMsgSendValidation(t *testing.T) { }{ {"", NewMsgSend(addr1, addr2, atom123)}, // valid send {"", NewMsgSend(addr1, addr2, atom123eth123)}, // valid send with multiple coins + {"", NewMsgSend(addrLong, addr2, atom123)}, // valid send with long addr sender + {"", NewMsgSend(addr1, addrLong, atom123)}, // valid send with long addr recipient {": invalid coins", NewMsgSend(addr1, addr2, atom0)}, // non positive coin {"123atom,0eth: invalid coins", NewMsgSend(addr1, addr2, atom123eth0)}, // non positive coin in multicoins {"Invalid sender address (empty address string is not allowed): invalid address", NewMsgSend(addrEmpty, addr2, atom123)}, - {"Invalid sender address (incorrect address length (expected: 20, actual: 33)): invalid address", NewMsgSend(addrTooLong, addr2, atom123)}, {"Invalid recipient address (empty address string is not allowed): invalid address", NewMsgSend(addr1, addrEmpty, atom123)}, - {"Invalid recipient address (incorrect address length (expected: 20, actual: 33)): invalid address", NewMsgSend(addr1, addrTooLong, atom123)}, } for _, tc := range cases { @@ -91,7 +91,7 @@ func TestInputValidation(t *testing.T) { addr1 := sdk.AccAddress([]byte("_______alice________")) addr2 := sdk.AccAddress([]byte("________bob_________")) addrEmpty := sdk.AccAddress([]byte("")) - addrTooLong := sdk.AccAddress([]byte("Accidentally used 33 bytes pubkey")) + addrLong := sdk.AccAddress([]byte("Purposefully long address")) someCoins := sdk.NewCoins(sdk.NewInt64Coin("atom", 123)) multiCoins := sdk.NewCoins(sdk.NewInt64Coin("atom", 123), sdk.NewInt64Coin("eth", 20)) @@ -109,9 +109,9 @@ func TestInputValidation(t *testing.T) { {"", NewInput(addr1, someCoins)}, {"", NewInput(addr2, someCoins)}, {"", NewInput(addr2, multiCoins)}, + {"", NewInput(addrLong, someCoins)}, {"empty address string is not allowed", NewInput(addrEmpty, someCoins)}, - {"incorrect address length (expected: 20, actual: 33)", NewInput(addrTooLong, someCoins)}, {": invalid coins", NewInput(addr1, emptyCoins)}, // invalid coins {": invalid coins", NewInput(addr1, emptyCoins2)}, // invalid coins {"10eth,0atom: invalid coins", NewInput(addr1, someEmptyCoins)}, // invalid coins @@ -132,7 +132,7 @@ func TestOutputValidation(t *testing.T) { addr1 := sdk.AccAddress([]byte("_______alice________")) addr2 := sdk.AccAddress([]byte("________bob_________")) addrEmpty := sdk.AccAddress([]byte("")) - addrTooLong := sdk.AccAddress([]byte("Accidentally used 33 bytes pubkey")) + addrLong := sdk.AccAddress([]byte("Purposefully long address")) someCoins := sdk.NewCoins(sdk.NewInt64Coin("atom", 123)) multiCoins := sdk.NewCoins(sdk.NewInt64Coin("atom", 123), sdk.NewInt64Coin("eth", 20)) @@ -150,9 +150,9 @@ func TestOutputValidation(t *testing.T) { {"", NewOutput(addr1, someCoins)}, {"", NewOutput(addr2, someCoins)}, {"", NewOutput(addr2, multiCoins)}, + {"", NewOutput(addrLong, someCoins)}, {"Invalid output address (empty address string is not allowed): invalid address", NewOutput(addrEmpty, someCoins)}, - {"Invalid output address (incorrect address length (expected: 20, actual: 33)): invalid address", NewOutput(addrTooLong, someCoins)}, {": invalid coins", NewOutput(addr1, emptyCoins)}, // invalid coins {": invalid coins", NewOutput(addr1, emptyCoins2)}, // invalid coins {"10eth,0atom: invalid coins", NewOutput(addr1, someEmptyCoins)}, // invalid coins @@ -251,8 +251,6 @@ func TestMsgMultiSendGetSigners(t *testing.T) { require.Equal(t, "[696E707574313131313131313131313131313131 696E707574323232323232323232323232323232 696E707574333333333333333333333333333333]", fmt.Sprintf("%v", res)) } -/* -// what to do w/ this test? func TestMsgSendSigners(t *testing.T) { signers := []sdk.AccAddress{ {1, 2, 3}, @@ -265,8 +263,7 @@ func TestMsgSendSigners(t *testing.T) { for i, signer := range signers { inputs[i] = NewInput(signer, someCoins) } - tx := NewMsgSend(inputs, nil) + tx := NewMsgMultiSend(inputs, nil) - require.Equal(t, signers, tx.Signers()) + require.Equal(t, signers, tx.GetSigners()) } -*/ diff --git a/x/distribution/types/keys.go b/x/distribution/types/keys.go index 12fe9b17b9ff..4f0f37f82303 100644 --- a/x/distribution/types/keys.go +++ b/x/distribution/types/keys.go @@ -4,6 +4,7 @@ import ( "encoding/binary" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" ) const ( @@ -27,19 +28,19 @@ const ( // // - 0x01: sdk.ConsAddress // -// - 0x02: ValidatorOutstandingRewards +// - 0x02: ValidatorOutstandingRewards // -// - 0x03: sdk.AccAddress +// - 0x03: sdk.AccAddress // -// - 0x04: DelegatorStartingInfo +// - 0x04: DelegatorStartingInfo // -// - 0x05: ValidatorHistoricalRewards +// - 0x05: ValidatorHistoricalRewards // -// - 0x06: ValidatorCurrentRewards +// - 0x06: ValidatorCurrentRewards // -// - 0x07: ValidatorCurrentRewards +// - 0x07: ValidatorCurrentRewards // -// - 0x08: ValidatorSlashEvent +// - 0x08: ValidatorSlashEvent var ( FeePoolKey = []byte{0x00} // key for global distribution state ProposerKey = []byte{0x01} // key for the proposer operator address @@ -53,47 +54,56 @@ var ( ValidatorSlashEventPrefix = []byte{0x08} // key for validator slash fraction ) -// gets an address from a validator's outstanding rewards key +// GetValidatorOutstandingRewardsAddress creates an address from a validator's outstanding rewards key. func GetValidatorOutstandingRewardsAddress(key []byte) (valAddr sdk.ValAddress) { - addr := key[1:] - if len(addr) != sdk.AddrLen { + // key is in the format: + // 0x02 + + // Remove prefix and address length. + addr := key[2:] + if len(addr) != int(key[1]) { panic("unexpected key length") } + return sdk.ValAddress(addr) } -// gets an address from a delegator's withdraw info key +// GetDelegatorWithdrawInfoAddress creates an address from a delegator's withdraw info key. func GetDelegatorWithdrawInfoAddress(key []byte) (delAddr sdk.AccAddress) { - addr := key[1:] - if len(addr) != sdk.AddrLen { + // key is in the format: + // 0x03 + + // Remove prefix and address length. + addr := key[2:] + if len(addr) != int(key[1]) { panic("unexpected key length") } + return sdk.AccAddress(addr) } -// gets the addresses from a delegator starting info key +// GetDelegatorStartingInfoAddresses creates the addresses from a delegator starting info key. func GetDelegatorStartingInfoAddresses(key []byte) (valAddr sdk.ValAddress, delAddr sdk.AccAddress) { - addr := key[1 : 1+sdk.AddrLen] - if len(addr) != sdk.AddrLen { + // key is in the format: + // 0x04 + valAddrLen := int(key[1]) + valAddr = sdk.ValAddress(key[2 : 2+valAddrLen]) + delAddrLen := int(key[2+valAddrLen]) + delAddr = sdk.AccAddress(key[3+valAddrLen:]) + if len(delAddr.Bytes()) != delAddrLen { panic("unexpected key length") } - valAddr = sdk.ValAddress(addr) - addr = key[1+sdk.AddrLen:] - if len(addr) != sdk.AddrLen { - panic("unexpected key length") - } - delAddr = sdk.AccAddress(addr) + return } -// gets the address & period from a validator's historical rewards key +// GetValidatorHistoricalRewardsAddressPeriod creates the address & period from a validator's historical rewards key. func GetValidatorHistoricalRewardsAddressPeriod(key []byte) (valAddr sdk.ValAddress, period uint64) { - addr := key[1 : 1+sdk.AddrLen] - if len(addr) != sdk.AddrLen { - panic("unexpected key length") - } - valAddr = sdk.ValAddress(addr) - b := key[1+sdk.AddrLen:] + // key is in the format: + // 0x05 + valAddrLen := int(key[1]) + valAddr = sdk.ValAddress(key[2 : 2+valAddrLen]) + b := key[2+valAddrLen:] if len(b) != 8 { panic("unexpected key length") } @@ -101,93 +111,104 @@ func GetValidatorHistoricalRewardsAddressPeriod(key []byte) (valAddr sdk.ValAddr return } -// gets the address from a validator's current rewards key +// GetValidatorCurrentRewardsAddress creates the address from a validator's current rewards key. func GetValidatorCurrentRewardsAddress(key []byte) (valAddr sdk.ValAddress) { - addr := key[1:] - if len(addr) != sdk.AddrLen { + // key is in the format: + // 0x06: ValidatorCurrentRewards + + // Remove prefix and address length. + addr := key[2:] + if len(addr) != int(key[1]) { panic("unexpected key length") } + return sdk.ValAddress(addr) } -// gets the address from a validator's accumulated commission key +// GetValidatorAccumulatedCommissionAddress creates the address from a validator's accumulated commission key. func GetValidatorAccumulatedCommissionAddress(key []byte) (valAddr sdk.ValAddress) { - addr := key[1:] - if len(addr) != sdk.AddrLen { + // key is in the format: + // 0x07: ValidatorCurrentRewards + + // Remove prefix and address length. + addr := key[2:] + if len(addr) != int(key[1]) { panic("unexpected key length") } + return sdk.ValAddress(addr) } -// gets the height from a validator's slash event key +// GetValidatorSlashEventAddressHeight creates the height from a validator's slash event key. func GetValidatorSlashEventAddressHeight(key []byte) (valAddr sdk.ValAddress, height uint64) { - addr := key[1 : 1+sdk.AddrLen] - if len(addr) != sdk.AddrLen { - panic("unexpected key length") - } - valAddr = sdk.ValAddress(addr) - startB := 1 + sdk.AddrLen + // key is in the format: + // 0x08: ValidatorSlashEvent + valAddrLen := int(key[1]) + valAddr = key[2 : 2+valAddrLen] + startB := 2 + valAddrLen b := key[startB : startB+8] // the next 8 bytes represent the height height = binary.BigEndian.Uint64(b) return } -// gets the outstanding rewards key for a validator +// GetValidatorOutstandingRewardsKey creates the outstanding rewards key for a validator. func GetValidatorOutstandingRewardsKey(valAddr sdk.ValAddress) []byte { - return append(ValidatorOutstandingRewardsPrefix, valAddr.Bytes()...) + return append(ValidatorOutstandingRewardsPrefix, address.MustLengthPrefix(valAddr.Bytes())...) } -// gets the key for a delegator's withdraw addr +// GetDelegatorWithdrawAddrKey creates the key for a delegator's withdraw addr. func GetDelegatorWithdrawAddrKey(delAddr sdk.AccAddress) []byte { - return append(DelegatorWithdrawAddrPrefix, delAddr.Bytes()...) + return append(DelegatorWithdrawAddrPrefix, address.MustLengthPrefix(delAddr.Bytes())...) } -// gets the key for a delegator's starting info +// GetDelegatorStartingInfoKey creates the key for a delegator's starting info. func GetDelegatorStartingInfoKey(v sdk.ValAddress, d sdk.AccAddress) []byte { - return append(append(DelegatorStartingInfoPrefix, v.Bytes()...), d.Bytes()...) + return append(append(DelegatorStartingInfoPrefix, address.MustLengthPrefix(v.Bytes())...), address.MustLengthPrefix(d.Bytes())...) } -// gets the prefix key for a validator's historical rewards +// GetValidatorHistoricalRewardsPrefix creates the prefix key for a validator's historical rewards. func GetValidatorHistoricalRewardsPrefix(v sdk.ValAddress) []byte { - return append(ValidatorHistoricalRewardsPrefix, v.Bytes()...) + return append(ValidatorHistoricalRewardsPrefix, address.MustLengthPrefix(v.Bytes())...) } -// gets the key for a validator's historical rewards +// GetValidatorHistoricalRewardsKey creates the key for a validator's historical rewards. func GetValidatorHistoricalRewardsKey(v sdk.ValAddress, k uint64) []byte { b := make([]byte, 8) binary.LittleEndian.PutUint64(b, k) - return append(append(ValidatorHistoricalRewardsPrefix, v.Bytes()...), b...) + return append(append(ValidatorHistoricalRewardsPrefix, address.MustLengthPrefix(v.Bytes())...), b...) } -// gets the key for a validator's current rewards +// GetValidatorCurrentRewardsKey creates the key for a validator's current rewards. func GetValidatorCurrentRewardsKey(v sdk.ValAddress) []byte { - return append(ValidatorCurrentRewardsPrefix, v.Bytes()...) + return append(ValidatorCurrentRewardsPrefix, address.MustLengthPrefix(v.Bytes())...) } -// gets the key for a validator's current commission +// GetValidatorAccumulatedCommissionKey creates the key for a validator's current commission. func GetValidatorAccumulatedCommissionKey(v sdk.ValAddress) []byte { - return append(ValidatorAccumulatedCommissionPrefix, v.Bytes()...) + return append(ValidatorAccumulatedCommissionPrefix, address.MustLengthPrefix(v.Bytes())...) } -// gets the prefix key for a validator's slash fractions +// GetValidatorSlashEventPrefix creates the prefix key for a validator's slash fractions. func GetValidatorSlashEventPrefix(v sdk.ValAddress) []byte { - return append(ValidatorSlashEventPrefix, v.Bytes()...) + return append(ValidatorSlashEventPrefix, address.MustLengthPrefix(v.Bytes())...) } -// gets the prefix key for a validator's slash fraction (ValidatorSlashEventPrefix + height) +// GetValidatorSlashEventKeyPrefix creates the prefix key for a validator's slash fraction (ValidatorSlashEventPrefix + height). func GetValidatorSlashEventKeyPrefix(v sdk.ValAddress, height uint64) []byte { heightBz := make([]byte, 8) binary.BigEndian.PutUint64(heightBz, height) + return append( ValidatorSlashEventPrefix, - append(v.Bytes(), heightBz...)..., + append(address.MustLengthPrefix(v.Bytes()), heightBz...)..., ) } -// gets the key for a validator's slash fraction +// GetValidatorSlashEventKey creates the key for a validator's slash fraction. func GetValidatorSlashEventKey(v sdk.ValAddress, height, period uint64) []byte { periodBz := make([]byte, 8) binary.BigEndian.PutUint64(periodBz, period) prefix := GetValidatorSlashEventKeyPrefix(v, height) + return append(prefix, periodBz...) } diff --git a/x/feegrant/types/key.go b/x/feegrant/types/key.go index e30427b136b4..7cd1ce4f8c8f 100644 --- a/x/feegrant/types/key.go +++ b/x/feegrant/types/key.go @@ -2,6 +2,7 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" ) const ( @@ -26,10 +27,10 @@ var ( // FeeAllowanceKey is the canonical key to store a grant from granter to grantee // We store by grantee first to allow searching by everyone who granted to you func FeeAllowanceKey(granter sdk.AccAddress, grantee sdk.AccAddress) []byte { - return append(append(FeeAllowanceKeyPrefix, grantee.Bytes()...), granter.Bytes()...) + return append(FeeAllowancePrefixByGrantee(grantee), address.MustLengthPrefix(granter.Bytes())...) } // FeeAllowancePrefixByGrantee returns a prefix to scan for all grants to this given address. func FeeAllowancePrefixByGrantee(grantee sdk.AccAddress) []byte { - return append(FeeAllowanceKeyPrefix, grantee.Bytes()...) + return append(FeeAllowanceKeyPrefix, address.MustLengthPrefix(grantee.Bytes())...) } diff --git a/x/gov/types/keys.go b/x/gov/types/keys.go index 7681116fc46a..fe98bcbf81c4 100644 --- a/x/gov/types/keys.go +++ b/x/gov/types/keys.go @@ -6,6 +6,7 @@ import ( "time" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" ) const ( @@ -33,9 +34,9 @@ const ( // // - 0x03: nextProposalID // -// - 0x10: Deposit +// - 0x10: Deposit // -// - 0x20: Voter +// - 0x20: Voter var ( ProposalsKeyPrefix = []byte{0x00} ActiveProposalQueuePrefix = []byte{0x01} @@ -93,7 +94,7 @@ func DepositsKey(proposalID uint64) []byte { // DepositKey key of a specific deposit from the store func DepositKey(proposalID uint64, depositorAddr sdk.AccAddress) []byte { - return append(DepositsKey(proposalID), depositorAddr.Bytes()...) + return append(DepositsKey(proposalID), address.MustLengthPrefix(depositorAddr.Bytes())...) } // VotesKey gets the first part of the votes key based on the proposalID @@ -103,7 +104,7 @@ func VotesKey(proposalID uint64) []byte { // VoteKey key of a specific vote from the store func VoteKey(proposalID uint64, voterAddr sdk.AccAddress) []byte { - return append(VotesKey(proposalID), voterAddr.Bytes()...) + return append(VotesKey(proposalID), address.MustLengthPrefix(voterAddr.Bytes())...) } // Split keys function; used for iterators @@ -154,11 +155,9 @@ func splitKeyWithTime(key []byte) (proposalID uint64, endTime time.Time) { } func splitKeyWithAddress(key []byte) (proposalID uint64, addr sdk.AccAddress) { - if len(key[1:]) != 8+sdk.AddrLen { - panic(fmt.Sprintf("unexpected key length (%d ≠ %d)", len(key), 8+sdk.AddrLen)) - } - + // Both Vote and Deposit store keys are of format: + // proposalID = GetProposalIDFromBytes(key[1:9]) - addr = sdk.AccAddress(key[9:]) + addr = sdk.AccAddress(key[10:]) return } diff --git a/x/gov/types/keys_test.go b/x/gov/types/keys_test.go index 80dfa7d207a3..30266f8f4d78 100644 --- a/x/gov/types/keys_test.go +++ b/x/gov/types/keys_test.go @@ -46,11 +46,6 @@ func TestDepositKeys(t *testing.T) { proposalID, depositorAddr := SplitKeyDeposit(key) require.Equal(t, int(proposalID), 2) require.Equal(t, addr, depositorAddr) - - // invalid key - addr2 := sdk.AccAddress("test1") - key = DepositKey(5, addr2) - require.Panics(t, func() { SplitKeyDeposit(key) }) } func TestVoteKeys(t *testing.T) { @@ -63,9 +58,4 @@ func TestVoteKeys(t *testing.T) { proposalID, voterAddr := SplitKeyDeposit(key) require.Equal(t, int(proposalID), 2) require.Equal(t, addr, voterAddr) - - // invalid key - addr2 := sdk.AccAddress("test1") - key = VoteKey(5, addr2) - require.Panics(t, func() { SplitKeyVote(key) }) } diff --git a/x/slashing/types/keys.go b/x/slashing/types/keys.go index c9792d22085f..f0049760f0a0 100644 --- a/x/slashing/types/keys.go +++ b/x/slashing/types/keys.go @@ -4,6 +4,7 @@ import ( "encoding/binary" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" ) const ( @@ -23,11 +24,11 @@ const ( // Keys for slashing store // Items are stored with the following key: values // -// - 0x01: ValidatorSigningInfo +// - 0x01: ValidatorSigningInfo // -// - 0x02: bool +// - 0x02: bool // -// - 0x03: crypto.PubKey +// - 0x03: cryptotypes.PubKey var ( ValidatorSigningInfoKeyPrefix = []byte{0x01} // Prefix for signing info ValidatorMissedBlockBitArrayKeyPrefix = []byte{0x02} // Prefix for missed block bit array @@ -36,31 +37,31 @@ var ( // ValidatorSigningInfoKey - stored by *Consensus* address (not operator address) func ValidatorSigningInfoKey(v sdk.ConsAddress) []byte { - return append(ValidatorSigningInfoKeyPrefix, v.Bytes()...) + return append(ValidatorSigningInfoKeyPrefix, address.MustLengthPrefix(v.Bytes())...) } // ValidatorSigningInfoAddress - extract the address from a validator signing info key func ValidatorSigningInfoAddress(key []byte) (v sdk.ConsAddress) { - addr := key[1:] - if len(addr) != sdk.AddrLen { - panic("unexpected key length") - } + // Remove prefix and address length. + addr := key[2:] + return sdk.ConsAddress(addr) } // ValidatorMissedBlockBitArrayPrefixKey - stored by *Consensus* address (not operator address) func ValidatorMissedBlockBitArrayPrefixKey(v sdk.ConsAddress) []byte { - return append(ValidatorMissedBlockBitArrayKeyPrefix, v.Bytes()...) + return append(ValidatorMissedBlockBitArrayKeyPrefix, address.MustLengthPrefix(v.Bytes())...) } // ValidatorMissedBlockBitArrayKey - stored by *Consensus* address (not operator address) func ValidatorMissedBlockBitArrayKey(v sdk.ConsAddress, i int64) []byte { b := make([]byte, 8) binary.LittleEndian.PutUint64(b, uint64(i)) + return append(ValidatorMissedBlockBitArrayPrefixKey(v), b...) } // AddrPubkeyRelationKey gets pubkey relation key used to get the pubkey from the address -func AddrPubkeyRelationKey(address []byte) []byte { - return append(AddrPubkeyRelationKeyPrefix, address...) +func AddrPubkeyRelationKey(addr []byte) []byte { + return append(AddrPubkeyRelationKeyPrefix, address.MustLengthPrefix(addr)...) } diff --git a/x/staking/keeper/val_state_change.go b/x/staking/keeper/val_state_change.go index f06994f44f70..52b739230076 100644 --- a/x/staking/keeper/val_state_change.go +++ b/x/staking/keeper/val_state_change.go @@ -12,7 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/staking/types" ) -// Calculate the ValidatorUpdates for the current block +// BlockValidatorUpdates calculates the ValidatorUpdates for the current block // Called in each EndBlock func (k Keeper) BlockValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate { // Calculate validator set changes. @@ -97,7 +97,7 @@ func (k Keeper) BlockValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate { return validatorUpdates } -// Apply and return accumulated updates to the bonded validator set. Also, +// ApplyAndReturnValidatorSetUpdates applies and return accumulated updates to the bonded validator set. Also, // * Updates the active valset as keyed by LastValidatorPowerKey. // * Updates the total power as keyed by LastTotalPowerKey. // * Updates validator status' according to updated powers. @@ -117,7 +117,10 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab // Retrieve the last validator set. // The persistent set is updated later in this function. // (see LastValidatorPowerKey). - last := k.getLastValidatorsByAddr(ctx) + last, err := k.getLastValidatorsByAddr(ctx) + if err != nil { + return nil, err + } // Iterate over validators, highest power to lowest. iterator := k.ValidatorsPowerStoreIterator(ctx) @@ -160,10 +163,11 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab } // fetch the old power bytes - var valAddrBytes [sdk.AddrLen]byte - - copy(valAddrBytes[:], valAddr[:]) - oldPowerBytes, found := last[valAddrBytes] + valAddrStr, err := sdk.Bech32ifyAddressBytes(sdk.Bech32PrefixValAddr, valAddr) + if err != nil { + return nil, err + } + oldPowerBytes, found := last[valAddrStr] newPower := validator.ConsensusPower() newPowerBytes := k.cdc.MustMarshalBinaryBare(&gogotypes.Int64Value{Value: newPower}) @@ -174,13 +178,17 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab k.SetLastValidatorPower(ctx, valAddr, newPower) } - delete(last, valAddrBytes) + delete(last, valAddrStr) count++ totalPower = totalPower.Add(sdk.NewInt(newPower)) } - noLongerBonded := sortNoLongerBonded(last) + noLongerBonded, err := sortNoLongerBonded(last) + if err != nil { + return nil, err + } + for _, valAddrBytes := range noLongerBonded { validator := k.mustGetValidator(ctx, sdk.ValAddress(valAddrBytes)) validator, err = k.bondedToUnbonding(ctx, validator) @@ -339,39 +347,46 @@ func (k Keeper) completeUnbondingValidator(ctx sdk.Context, validator types.Vali return validator } -// map of operator addresses to serialized power -type validatorsByAddr map[[sdk.AddrLen]byte][]byte +// map of operator bech32-addresses to serialized power +// We use bech32 strings here, because we can't have slices as keys: map[[]byte][]byte +type validatorsByAddr map[string][]byte // get the last validator set -func (k Keeper) getLastValidatorsByAddr(ctx sdk.Context) validatorsByAddr { +func (k Keeper) getLastValidatorsByAddr(ctx sdk.Context) (validatorsByAddr, error) { last := make(validatorsByAddr) iterator := k.LastValidatorsIterator(ctx) defer iterator.Close() for ; iterator.Valid(); iterator.Next() { - var valAddr [sdk.AddrLen]byte - // extract the validator address from the key (prefix is 1-byte) - copy(valAddr[:], iterator.Key()[1:]) + // extract the validator address from the key (prefix is 1-byte, addrLen is 1-byte) + valAddr := types.AddressFromLastValidatorPowerKey(iterator.Key()) + valAddrStr, err := sdk.Bech32ifyAddressBytes(sdk.Bech32PrefixValAddr, valAddr) + if err != nil { + return nil, err + } + powerBytes := iterator.Value() - last[valAddr] = make([]byte, len(powerBytes)) - copy(last[valAddr], powerBytes) + last[valAddrStr] = make([]byte, len(powerBytes)) + copy(last[valAddrStr], powerBytes) } - return last + return last, nil } // given a map of remaining validators to previous bonded power // returns the list of validators to be unbonded, sorted by operator address -func sortNoLongerBonded(last validatorsByAddr) [][]byte { +func sortNoLongerBonded(last validatorsByAddr) ([][]byte, error) { // sort the map keys for determinism noLongerBonded := make([][]byte, len(last)) index := 0 - for valAddrBytes := range last { - valAddr := make([]byte, sdk.AddrLen) - copy(valAddr, valAddrBytes[:]) - noLongerBonded[index] = valAddr + for valAddrStr := range last { + valAddrBytes, err := sdk.ValAddressFromBech32(valAddrStr) + if err != nil { + return nil, err + } + noLongerBonded[index] = valAddrBytes index++ } // sorted by address - order doesn't matter @@ -380,5 +395,5 @@ func sortNoLongerBonded(last validatorsByAddr) [][]byte { return bytes.Compare(noLongerBonded[i], noLongerBonded[j]) == -1 }) - return noLongerBonded + return noLongerBonded, nil } diff --git a/x/staking/keeper/validator.go b/x/staking/keeper/validator.go index edb00ddba55b..9fa6a0ca0a0b 100644 --- a/x/staking/keeper/validator.go +++ b/x/staking/keeper/validator.go @@ -327,7 +327,7 @@ func (k Keeper) IterateLastValidatorPowers(ctx sdk.Context, handler func(operato defer iter.Close() for ; iter.Valid(); iter.Next() { - addr := sdk.ValAddress(iter.Key()[len(types.LastValidatorPowerKey):]) + addr := sdk.ValAddress(types.AddressFromLastValidatorPowerKey(iter.Key())) intV := &gogotypes.Int64Value{} k.cdc.MustUnmarshalBinaryBare(iter.Value(), intV) diff --git a/x/staking/types/keys.go b/x/staking/types/keys.go index 40d62244a041..1854ddac6159 100644 --- a/x/staking/types/keys.go +++ b/x/staking/types/keys.go @@ -8,6 +8,7 @@ import ( "time" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" ) const ( @@ -48,24 +49,29 @@ var ( HistoricalInfoKey = []byte{0x50} // prefix for the historical info ) -// gets the key for the validator with address +// GetValidatorKey creates the key for the validator with address // VALUE: staking/Validator func GetValidatorKey(operatorAddr sdk.ValAddress) []byte { - return append(ValidatorsKey, operatorAddr.Bytes()...) + return append(ValidatorsKey, address.MustLengthPrefix(operatorAddr)...) } -// gets the key for the validator with pubkey +// GetValidatorByConsAddrKey creates the key for the validator with pubkey // VALUE: validator operator address ([]byte) func GetValidatorByConsAddrKey(addr sdk.ConsAddress) []byte { - return append(ValidatorsByConsAddrKey, addr.Bytes()...) + return append(ValidatorsByConsAddrKey, address.MustLengthPrefix(addr)...) } -// Get the validator operator address from LastValidatorPowerKey +// AddressFromValidatorsKey creates the validator operator address from ValidatorsKey +func AddressFromValidatorsKey(key []byte) []byte { + return key[2:] // remove prefix bytes and address length +} + +// AddressFromLastValidatorPowerKey creates the validator operator address from LastValidatorPowerKey func AddressFromLastValidatorPowerKey(key []byte) []byte { - return key[1:] // remove prefix bytes + return key[2:] // remove prefix bytes and address length } -// get the validator by power index. +// GetValidatorsByPowerIndexKey creates the validator by power index. // Power index is the key used in the power-store, and represents the relative // power ranking of the validator. // VALUE: validator operator address ([]byte) @@ -80,39 +86,39 @@ func GetValidatorsByPowerIndexKey(validator Validator) []byte { powerBytes := consensusPowerBytes powerBytesLen := len(powerBytes) // 8 - // key is of format prefix || powerbytes || addrBytes - key := make([]byte, 1+powerBytesLen+sdk.AddrLen) - - key[0] = ValidatorsByPowerIndexKey[0] - copy(key[1:powerBytesLen+1], powerBytes) addr, err := sdk.ValAddressFromBech32(validator.OperatorAddress) if err != nil { panic(err) } operAddrInvr := sdk.CopyBytes(addr) + addrLen := len(operAddrInvr) for i, b := range operAddrInvr { operAddrInvr[i] = ^b } - copy(key[powerBytesLen+1:], operAddrInvr) + // key is of format prefix || powerbytes || addrLen (1byte) || addrBytes + key := make([]byte, 1+powerBytesLen+1+addrLen) + + key[0] = ValidatorsByPowerIndexKey[0] + copy(key[1:powerBytesLen+1], powerBytes) + key[powerBytesLen+1] = byte(addrLen) + copy(key[powerBytesLen+2:], operAddrInvr) return key } -// get the bonded validator index key for an operator address +// GetLastValidatorPowerKey creates the bonded validator index key for an operator address func GetLastValidatorPowerKey(operator sdk.ValAddress) []byte { - return append(LastValidatorPowerKey, operator...) + return append(LastValidatorPowerKey, address.MustLengthPrefix(operator)...) } -// parse the validators operator address from power rank key +// ParseValidatorPowerRankKey parses the validators operator address from power rank key func ParseValidatorPowerRankKey(key []byte) (operAddr []byte) { powerBytesLen := 8 - if len(key) != 1+powerBytesLen+sdk.AddrLen { - panic("Invalid validator power rank key length") - } - operAddr = sdk.CopyBytes(key[powerBytesLen+1:]) + // key is of format prefix (1 byte) || powerbytes || addrLen (1byte) || addrBytes + operAddr = sdk.CopyBytes(key[powerBytesLen+2:]) for i, b := range operAddr { operAddr[i] = ^b @@ -165,55 +171,51 @@ func ParseValidatorQueueKey(bz []byte) (time.Time, int64, error) { return ts, int64(height), nil } -// gets the key for delegator bond with validator +// GetDelegationKey creates the key for delegator bond with validator // VALUE: staking/Delegation func GetDelegationKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { - return append(GetDelegationsKey(delAddr), valAddr.Bytes()...) + return append(GetDelegationsKey(delAddr), address.MustLengthPrefix(valAddr)...) } -// gets the prefix for a delegator for all validators +// GetDelegationsKey creates the prefix for a delegator for all validators func GetDelegationsKey(delAddr sdk.AccAddress) []byte { - return append(DelegationKey, delAddr.Bytes()...) + return append(DelegationKey, address.MustLengthPrefix(delAddr)...) } -// gets the key for an unbonding delegation by delegator and validator addr +// GetUBDKey creates the key for an unbonding delegation by delegator and validator addr // VALUE: staking/UnbondingDelegation func GetUBDKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { - return append( - GetUBDsKey(delAddr.Bytes()), - valAddr.Bytes()...) + return append(GetUBDsKey(delAddr.Bytes()), address.MustLengthPrefix(valAddr)...) } -// gets the index-key for an unbonding delegation, stored by validator-index +// GetUBDByValIndexKey creates the index-key for an unbonding delegation, stored by validator-index // VALUE: none (key rearrangement used) func GetUBDByValIndexKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { - return append(GetUBDsByValIndexKey(valAddr), delAddr.Bytes()...) + return append(GetUBDsByValIndexKey(valAddr), address.MustLengthPrefix(delAddr)...) } -// rearranges the ValIndexKey to get the UBDKey +// GetUBDKeyFromValIndexKey rearranges the ValIndexKey to get the UBDKey func GetUBDKeyFromValIndexKey(indexKey []byte) []byte { addrs := indexKey[1:] // remove prefix bytes - if len(addrs) != 2*sdk.AddrLen { - panic("unexpected key length") - } - valAddr := addrs[:sdk.AddrLen] - delAddr := addrs[sdk.AddrLen:] + valAddrLen := addrs[0] + valAddr := addrs[1 : 1+valAddrLen] + delAddr := addrs[valAddrLen+2:] return GetUBDKey(delAddr, valAddr) } -// gets the prefix for all unbonding delegations from a delegator +// GetUBDsKey creates the prefix for all unbonding delegations from a delegator func GetUBDsKey(delAddr sdk.AccAddress) []byte { - return append(UnbondingDelegationKey, delAddr.Bytes()...) + return append(UnbondingDelegationKey, address.MustLengthPrefix(delAddr)...) } -// gets the prefix keyspace for the indexes of unbonding delegations for a validator +// GetUBDsByValIndexKey creates the prefix keyspace for the indexes of unbonding delegations for a validator func GetUBDsByValIndexKey(valAddr sdk.ValAddress) []byte { - return append(UnbondingDelegationByValIndexKey, valAddr.Bytes()...) + return append(UnbondingDelegationByValIndexKey, address.MustLengthPrefix(valAddr)...) } -// gets the prefix for all unbonding delegations from a delegator +// GetUnbondingDelegationTimeKey creates the prefix for all unbonding delegations from a delegator func GetUnbondingDelegationTimeKey(timestamp time.Time) []byte { bz := sdk.FormatTimeBytes(timestamp) return append(UnbondingQueueKey, bz...) @@ -222,69 +224,76 @@ func GetUnbondingDelegationTimeKey(timestamp time.Time) []byte { // GetREDKey returns a key prefix for indexing a redelegation from a delegator // and source validator to a destination validator. func GetREDKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { - key := make([]byte, 1+sdk.AddrLen*3) + // key is of the form GetREDsKey || valSrcAddrLen (1 byte) || valSrcAddr || valDstAddrLen (1 byte) || valDstAddr + key := make([]byte, 1+3+len(delAddr)+len(valSrcAddr)+len(valDstAddr)) - copy(key[0:sdk.AddrLen+1], GetREDsKey(delAddr.Bytes())) - copy(key[sdk.AddrLen+1:2*sdk.AddrLen+1], valSrcAddr.Bytes()) - copy(key[2*sdk.AddrLen+1:3*sdk.AddrLen+1], valDstAddr.Bytes()) + copy(key[0:2+len(delAddr)], GetREDsKey(delAddr.Bytes())) + key[2+len(delAddr)] = byte(len(valSrcAddr)) + copy(key[3+len(delAddr):3+len(delAddr)+len(valSrcAddr)], valSrcAddr.Bytes()) + key[3+len(delAddr)+len(valSrcAddr)] = byte(len(valDstAddr)) + copy(key[4+len(delAddr)+len(valSrcAddr):], valDstAddr.Bytes()) return key } -// gets the index-key for a redelegation, stored by source-validator-index +// GetREDByValSrcIndexKey creates the index-key for a redelegation, stored by source-validator-index // VALUE: none (key rearrangement used) func GetREDByValSrcIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { REDSFromValsSrcKey := GetREDsFromValSrcIndexKey(valSrcAddr) offset := len(REDSFromValsSrcKey) - // key is of the form REDSFromValsSrcKey || delAddr || valDstAddr - key := make([]byte, len(REDSFromValsSrcKey)+2*sdk.AddrLen) + // key is of the form REDSFromValsSrcKey || delAddrLen (1 byte) || delAddr || valDstAddrLen (1 byte) || valDstAddr + key := make([]byte, offset+2+len(delAddr)+len(valDstAddr)) copy(key[0:offset], REDSFromValsSrcKey) - copy(key[offset:offset+sdk.AddrLen], delAddr.Bytes()) - copy(key[offset+sdk.AddrLen:offset+2*sdk.AddrLen], valDstAddr.Bytes()) + key[offset] = byte(len(delAddr)) + copy(key[offset+1:offset+1+len(delAddr)], delAddr.Bytes()) + key[offset+1+len(delAddr)] = byte(len(valDstAddr)) + copy(key[offset+2+len(delAddr):], valDstAddr.Bytes()) return key } -// gets the index-key for a redelegation, stored by destination-validator-index +// GetREDByValDstIndexKey creates the index-key for a redelegation, stored by destination-validator-index // VALUE: none (key rearrangement used) func GetREDByValDstIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { REDSToValsDstKey := GetREDsToValDstIndexKey(valDstAddr) offset := len(REDSToValsDstKey) - // key is of the form REDSToValsDstKey || delAddr || valSrcAddr - key := make([]byte, len(REDSToValsDstKey)+2*sdk.AddrLen) + // key is of the form REDSToValsDstKey || delAddrLen (1 byte) || delAddr || valSrcAddrLen (1 byte) || valSrcAddr + key := make([]byte, offset+2+len(delAddr)+len(valSrcAddr)) copy(key[0:offset], REDSToValsDstKey) - copy(key[offset:offset+sdk.AddrLen], delAddr.Bytes()) - copy(key[offset+sdk.AddrLen:offset+2*sdk.AddrLen], valSrcAddr.Bytes()) + key[offset] = byte(len(delAddr)) + copy(key[offset+1:offset+1+len(delAddr)], delAddr.Bytes()) + key[offset+1+len(delAddr)] = byte(len(valSrcAddr)) + copy(key[offset+2+len(delAddr):], valSrcAddr.Bytes()) return key } // GetREDKeyFromValSrcIndexKey rearranges the ValSrcIndexKey to get the REDKey func GetREDKeyFromValSrcIndexKey(indexKey []byte) []byte { - // note that first byte is prefix byte - if len(indexKey) != 3*sdk.AddrLen+1 { - panic("unexpected key length") - } + // note that first byte is prefix byte, which we remove + addrs := indexKey[1:] - valSrcAddr := indexKey[1 : sdk.AddrLen+1] - delAddr := indexKey[sdk.AddrLen+1 : 2*sdk.AddrLen+1] - valDstAddr := indexKey[2*sdk.AddrLen+1 : 3*sdk.AddrLen+1] + valSrcAddrLen := addrs[0] + valSrcAddr := addrs[1 : valSrcAddrLen+1] + delAddrLen := addrs[valSrcAddrLen+1] + delAddr := addrs[valSrcAddrLen+2 : valSrcAddrLen+2+delAddrLen] + valDstAddr := addrs[valSrcAddrLen+delAddrLen+3:] return GetREDKey(delAddr, valSrcAddr, valDstAddr) } // GetREDKeyFromValDstIndexKey rearranges the ValDstIndexKey to get the REDKey func GetREDKeyFromValDstIndexKey(indexKey []byte) []byte { - // note that first byte is prefix byte - if len(indexKey) != 3*sdk.AddrLen+1 { - panic("unexpected key length") - } + // note that first byte is prefix byte, which we remove + addrs := indexKey[1:] - valDstAddr := indexKey[1 : sdk.AddrLen+1] - delAddr := indexKey[sdk.AddrLen+1 : 2*sdk.AddrLen+1] - valSrcAddr := indexKey[2*sdk.AddrLen+1 : 3*sdk.AddrLen+1] + valDstAddrLen := addrs[0] + valDstAddr := addrs[1 : valDstAddrLen+1] + delAddrLen := addrs[valDstAddrLen+1] + delAddr := addrs[valDstAddrLen+2 : valDstAddrLen+2+delAddrLen] + valSrcAddr := addrs[valDstAddrLen+delAddrLen+3:] return GetREDKey(delAddr, valSrcAddr, valDstAddr) } @@ -299,25 +308,25 @@ func GetRedelegationTimeKey(timestamp time.Time) []byte { // GetREDsKey returns a key prefix for indexing a redelegation from a delegator // address. func GetREDsKey(delAddr sdk.AccAddress) []byte { - return append(RedelegationKey, delAddr.Bytes()...) + return append(RedelegationKey, address.MustLengthPrefix(delAddr)...) } // GetREDsFromValSrcIndexKey returns a key prefix for indexing a redelegation to // a source validator. func GetREDsFromValSrcIndexKey(valSrcAddr sdk.ValAddress) []byte { - return append(RedelegationByValSrcIndexKey, valSrcAddr.Bytes()...) + return append(RedelegationByValSrcIndexKey, address.MustLengthPrefix(valSrcAddr)...) } // GetREDsToValDstIndexKey returns a key prefix for indexing a redelegation to a // destination (target) validator. func GetREDsToValDstIndexKey(valDstAddr sdk.ValAddress) []byte { - return append(RedelegationByValDstIndexKey, valDstAddr.Bytes()...) + return append(RedelegationByValDstIndexKey, address.MustLengthPrefix(valDstAddr)...) } // GetREDsByDelToValDstIndexKey returns a key prefix for indexing a redelegation // from an address to a source validator. func GetREDsByDelToValDstIndexKey(delAddr sdk.AccAddress, valDstAddr sdk.ValAddress) []byte { - return append(GetREDsToValDstIndexKey(valDstAddr), delAddr.Bytes()...) + return append(GetREDsToValDstIndexKey(valDstAddr), address.MustLengthPrefix(delAddr)...) } // GetHistoricalInfoKey returns a key prefix for indexing HistoricalInfo objects. diff --git a/x/staking/types/keys_test.go b/x/staking/types/keys_test.go index 0f63617f26b3..949c7caedb66 100644 --- a/x/staking/types/keys_test.go +++ b/x/staking/types/keys_test.go @@ -37,10 +37,10 @@ func TestGetValidatorPowerRank(t *testing.T) { validator types.Validator wantHex string }{ - {val1, "2300000000000000009c288ede7df62742fc3b7d0962045a8cef0f79f6"}, - {val2, "2300000000000000019c288ede7df62742fc3b7d0962045a8cef0f79f6"}, - {val3, "23000000000000000a9c288ede7df62742fc3b7d0962045a8cef0f79f6"}, - {val4, "2300000100000000009c288ede7df62742fc3b7d0962045a8cef0f79f6"}, + {val1, "230000000000000000149c288ede7df62742fc3b7d0962045a8cef0f79f6"}, + {val2, "230000000000000001149c288ede7df62742fc3b7d0962045a8cef0f79f6"}, + {val3, "23000000000000000a149c288ede7df62742fc3b7d0962045a8cef0f79f6"}, + {val4, "230000010000000000149c288ede7df62742fc3b7d0962045a8cef0f79f6"}, } for i, tt := range tests { got := hex.EncodeToString(types.GetValidatorsByPowerIndexKey(tt.validator)) @@ -57,11 +57,11 @@ func TestGetREDByValDstIndexKey(t *testing.T) { wantHex string }{ {sdk.AccAddress(keysAddr1), sdk.ValAddress(keysAddr1), sdk.ValAddress(keysAddr1), - "3663d771218209d8bd03c482f69dfba57310f0860963d771218209d8bd03c482f69dfba57310f0860963d771218209d8bd03c482f69dfba57310f08609"}, + "361463d771218209d8bd03c482f69dfba57310f086091463d771218209d8bd03c482f69dfba57310f086091463d771218209d8bd03c482f69dfba57310f08609"}, {sdk.AccAddress(keysAddr1), sdk.ValAddress(keysAddr2), sdk.ValAddress(keysAddr3), - "363ab62f0d93849be495e21e3e9013a517038f45bd63d771218209d8bd03c482f69dfba57310f086095ef3b5f25c54946d4a89fc0d09d2f126614540f2"}, + "36143ab62f0d93849be495e21e3e9013a517038f45bd1463d771218209d8bd03c482f69dfba57310f08609145ef3b5f25c54946d4a89fc0d09d2f126614540f2"}, {sdk.AccAddress(keysAddr2), sdk.ValAddress(keysAddr1), sdk.ValAddress(keysAddr3), - "363ab62f0d93849be495e21e3e9013a517038f45bd5ef3b5f25c54946d4a89fc0d09d2f126614540f263d771218209d8bd03c482f69dfba57310f08609"}, + "36143ab62f0d93849be495e21e3e9013a517038f45bd145ef3b5f25c54946d4a89fc0d09d2f126614540f21463d771218209d8bd03c482f69dfba57310f08609"}, } for i, tt := range tests { got := hex.EncodeToString(types.GetREDByValDstIndexKey(tt.delAddr, tt.valSrcAddr, tt.valDstAddr)) @@ -78,11 +78,11 @@ func TestGetREDByValSrcIndexKey(t *testing.T) { wantHex string }{ {sdk.AccAddress(keysAddr1), sdk.ValAddress(keysAddr1), sdk.ValAddress(keysAddr1), - "3563d771218209d8bd03c482f69dfba57310f0860963d771218209d8bd03c482f69dfba57310f0860963d771218209d8bd03c482f69dfba57310f08609"}, + "351463d771218209d8bd03c482f69dfba57310f086091463d771218209d8bd03c482f69dfba57310f086091463d771218209d8bd03c482f69dfba57310f08609"}, {sdk.AccAddress(keysAddr1), sdk.ValAddress(keysAddr2), sdk.ValAddress(keysAddr3), - "355ef3b5f25c54946d4a89fc0d09d2f126614540f263d771218209d8bd03c482f69dfba57310f086093ab62f0d93849be495e21e3e9013a517038f45bd"}, + "35145ef3b5f25c54946d4a89fc0d09d2f126614540f21463d771218209d8bd03c482f69dfba57310f08609143ab62f0d93849be495e21e3e9013a517038f45bd"}, {sdk.AccAddress(keysAddr2), sdk.ValAddress(keysAddr1), sdk.ValAddress(keysAddr3), - "3563d771218209d8bd03c482f69dfba57310f086095ef3b5f25c54946d4a89fc0d09d2f126614540f23ab62f0d93849be495e21e3e9013a517038f45bd"}, + "351463d771218209d8bd03c482f69dfba57310f08609145ef3b5f25c54946d4a89fc0d09d2f126614540f2143ab62f0d93849be495e21e3e9013a517038f45bd"}, } for i, tt := range tests { got := hex.EncodeToString(types.GetREDByValSrcIndexKey(tt.delAddr, tt.valSrcAddr, tt.valDstAddr)) From f9da95ad0952b6800e707aeb8ba008427798781b Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Tue, 2 Feb 2021 10:59:25 +0100 Subject: [PATCH 094/152] Fix keyring import from older versions. (#8436) Co-authored-by: Alessio Treglia Co-authored-by: sahith-narahari --- client/keys/migrate.go | 26 ++++++---- client/keys/testdata/keys/keys.db/000002.ldb | Bin 391 -> 0 bytes client/keys/testdata/keys/keys.db/CURRENT | 2 +- client/keys/testdata/keys/keys.db/CURRENT.bak | 2 +- client/keys/testdata/keys/keys.db/LOG | 48 +++++++++++------- .../testdata/keys/keys.db/MANIFEST-000004 | Bin 237 -> 0 bytes .../testdata/keys/keys.db/MANIFEST-000005 | Bin 0 -> 41 bytes crypto/keyring/keyring.go | 1 + 8 files changed, 49 insertions(+), 30 deletions(-) delete mode 100644 client/keys/testdata/keys/keys.db/000002.ldb delete mode 100644 client/keys/testdata/keys/keys.db/MANIFEST-000004 create mode 100644 client/keys/testdata/keys/keys.db/MANIFEST-000005 diff --git a/client/keys/migrate.go b/client/keys/migrate.go index d80bbe163097..836a2655b087 100644 --- a/client/keys/migrate.go +++ b/client/keys/migrate.go @@ -62,7 +62,7 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { var ( tmpDir string - migrator keyring.InfoImporter + migrator keyring.Importer ) if dryRun, _ := cmd.Flags().GetBool(flags.FlagDryRun); dryRun { @@ -73,10 +73,10 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { defer os.RemoveAll(tmpDir) - migrator, err = keyring.NewInfoImporter(keyringServiceName, "test", tmpDir, buf) + migrator, err = keyring.New(keyringServiceName, keyring.BackendTest, tmpDir, buf) } else { backend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend) - migrator, err = keyring.NewInfoImporter(keyringServiceName, backend, rootDir, buf) + migrator, err = keyring.New(keyringServiceName, backend, rootDir, buf) } if err != nil { @@ -86,12 +86,12 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { )) } - for _, key := range oldKeys { - legKeyInfo, err := legacyKb.Export(key.GetName()) - if err != nil { - return err - } + if len(oldKeys) == 0 { + cmd.Print("Migration Aborted: no keys to migrate") + return nil + } + for _, key := range oldKeys { keyName := key.GetName() keyType := key.GetType() @@ -107,7 +107,12 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { } if keyType != keyring.TypeLocal { - if err := migrator.Import(keyName, legKeyInfo); err != nil { + pubkeyArmor, err := legacyKb.ExportPubKey(keyName) + if err != nil { + return err + } + + if err := migrator.ImportPubKey(keyName, pubkeyArmor); err != nil { return err } @@ -127,10 +132,11 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { return err } - if err := migrator.Import(keyName, armoredPriv); err != nil { + if err := migrator.ImportPrivKey(keyName, armoredPriv, migratePassphrase); err != nil { return err } } + cmd.Print("Migration Complete") return err } diff --git a/client/keys/testdata/keys/keys.db/000002.ldb b/client/keys/testdata/keys/keys.db/000002.ldb deleted file mode 100644 index b36586df3626e4a01631c987005dd5b167ff1da2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 391 zcmey$^r4Z#RxCNcI5)r8Fr~Dl+#<2KsJx`KtSZ&C+#n^bq%tF`u)-ugH7~cY)V$I% zr?5&dF(suawYZp(g#iqTO7lVsQW8s2opV#-y;CcV^fL3(^4ZPAathMRi}EtE%8be? z%1q6&N-NC^O3Kqxat-nfiYqI#QcBBG%aVb{ar!ebvHCgrGpHDX^)kqL7g=R6a7wZ; zGIE+rc**mTQf0Uyr1m=MWxFC%+6+;l*L&_w+s))UMK~hzht#w>p1XUJc$A%Z zPwESPNR;9%PE9T_GBwLK6yWnVVl8E1WG;$fU@+p1Im5hYq0HxtQ@kC!+?#3MRPJ a`@iD$YnizAFo}VL@PqK*4c#iG?zaJJVsO>~ diff --git a/client/keys/testdata/keys/keys.db/CURRENT b/client/keys/testdata/keys/keys.db/CURRENT index cacca7574c03..aa5bb8ea5090 100644 --- a/client/keys/testdata/keys/keys.db/CURRENT +++ b/client/keys/testdata/keys/keys.db/CURRENT @@ -1 +1 @@ -MANIFEST-000004 +MANIFEST-000005 diff --git a/client/keys/testdata/keys/keys.db/CURRENT.bak b/client/keys/testdata/keys/keys.db/CURRENT.bak index feda7d6b2481..4fb1dad19e03 100644 --- a/client/keys/testdata/keys/keys.db/CURRENT.bak +++ b/client/keys/testdata/keys/keys.db/CURRENT.bak @@ -1 +1 @@ -MANIFEST-000000 +MANIFEST-000003 diff --git a/client/keys/testdata/keys/keys.db/LOG b/client/keys/testdata/keys/keys.db/LOG index 386101e4fb91..e37648b855bb 100644 --- a/client/keys/testdata/keys/keys.db/LOG +++ b/client/keys/testdata/keys/keys.db/LOG @@ -1,18 +1,30 @@ -=============== Mar 30, 2020 (CEST) =============== -02:07:34.137606 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -02:07:34.144547 db@open opening -02:07:34.144770 version@stat F·[] S·0B[] Sc·[] -02:07:34.145843 db@janitor F·2 G·0 -02:07:34.145875 db@open done T·1.315251ms -02:07:34.335635 db@close closing -02:07:34.335736 db@close done T·98.95µs -=============== Mar 30, 2020 (CEST) =============== -02:08:33.239115 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -02:08:33.239264 version@stat F·[] S·0B[] Sc·[] -02:08:33.239281 db@open opening -02:08:33.239310 journal@recovery F·1 -02:08:33.239398 journal@recovery recovering @1 -02:08:33.322008 memdb@flush created L0@2 N·4 S·391B "cos..ess,v4":"run..nfo,v3" -02:08:33.323091 version@stat F·[1] S·391B[391B] Sc·[0.25] -02:08:33.421979 db@janitor F·3 G·0 -02:08:33.422153 db@open done T·182.707962ms +=============== Feb 2, 2021 (IST) =============== +00:03:25.348369 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +00:03:25.350695 db@open opening +00:03:25.350888 version@stat F·[] S·0B[] Sc·[] +00:03:25.351864 db@janitor F·2 G·0 +00:03:25.351881 db@open done T·1.169825ms +00:03:25.351895 db@close closing +00:03:25.351929 db@close done T·33.042µs +=============== Feb 2, 2021 (IST) =============== +00:03:34.450638 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +00:03:34.450722 version@stat F·[] S·0B[] Sc·[] +00:03:34.450737 db@open opening +00:03:34.450765 journal@recovery F·1 +00:03:34.450851 journal@recovery recovering @1 +00:03:34.451173 version@stat F·[] S·0B[] Sc·[] +00:03:34.454278 db@janitor F·2 G·0 +00:03:34.454298 db@open done T·3.548046ms +00:03:34.454307 db@close closing +00:03:34.454327 db@close done T·19.017µs +=============== Feb 2, 2021 (IST) =============== +00:03:42.025705 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +00:03:42.025892 version@stat F·[] S·0B[] Sc·[] +00:03:42.025907 db@open opening +00:03:42.025943 journal@recovery F·1 +00:03:42.026790 journal@recovery recovering @2 +00:03:42.026946 version@stat F·[] S·0B[] Sc·[] +00:03:42.031645 db@janitor F·2 G·0 +00:03:42.031661 db@open done T·5.750008ms +00:03:42.283102 db@close closing +00:03:42.283162 db@close done T·58.775µs diff --git a/client/keys/testdata/keys/keys.db/MANIFEST-000004 b/client/keys/testdata/keys/keys.db/MANIFEST-000004 deleted file mode 100644 index 557b4bdbbc93fd41441cfe30d1ca16f08f47f344..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 237 zcmeykNagJ_21Z7yoYb<^oRlOzr^=Gl^338?=ltA)#G=HK{30f1W>ywfb_S+)X4~Za z;@tdV!<5pJa*M>`qVkf`vZ_?ma)Xq#lFE#%!U~i0)V$onQu9j7oWd%-#FUhx)Z$`B l76veoD=N(kEl5c$Np;RmiT6&eG}6n=OUq|uhDg)i1^~DrOBnzF diff --git a/client/keys/testdata/keys/keys.db/MANIFEST-000005 b/client/keys/testdata/keys/keys.db/MANIFEST-000005 new file mode 100644 index 0000000000000000000000000000000000000000..a9e8a261c7882e802f65360dc49782db7df6fb77 GIT binary patch literal 41 wcmYcef4W17fss)vC$%g!CnZVGsj?)sJhM2}IX|}`u_&=5zle#2nT>@304?eb82|tP literal 0 HcmV?d00001 diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index f88ffdc37010..164e6bfc19d5 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -108,6 +108,7 @@ type Signer interface { type Importer interface { // ImportPrivKey imports ASCII armored passphrase-encrypted private keys. ImportPrivKey(uid, armor, passphrase string) error + // ImportPubKey imports ASCII armored public keys. ImportPubKey(uid string, armor string) error } From 15d83f5dac95f4afeb9e266d14f044258e4d5744 Mon Sep 17 00:00:00 2001 From: SaReN Date: Tue, 2 Feb 2021 17:04:23 +0530 Subject: [PATCH 095/152] Add changelog (#8490) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a5fa83652ca..6c02349468f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (simapp) [\#8418](https://github.com/cosmos/cosmos-sdk/pull/8418) Add balance coin to supply when adding a new genesis account * (x/bank) [\#8417](https://github.com/cosmos/cosmos-sdk/pull/8417) Validate balances and coin denom metadata on genesis * (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value +* (client/keys) [\#8436](https://github.com/cosmos/cosmos-sdk/pull/8436) Fix key migration issue ## [v0.40.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.1) - 2021-01-19 From ce161c4f0c52689f199e3d0376b41f581394861e Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Tue, 2 Feb 2021 10:57:58 -0600 Subject: [PATCH 096/152] fix: tendermint subcommands should not create missing files (#8481) If the user specifies an incorrect `--home`, then the old behaviour would automatically populate it with fresh values, but we should fail instead. --- CHANGELOG.md | 2 ++ server/tm_cmds.go | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c02349468f1..73b4ff3ecd3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/bank) [\#8417](https://github.com/cosmos/cosmos-sdk/pull/8417) Validate balances and coin denom metadata on genesis * (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value * (client/keys) [\#8436](https://github.com/cosmos/cosmos-sdk/pull/8436) Fix key migration issue +* (server) [\#8481](https://github.com/cosmos/cosmos-sdk/pull/8481) Don't create + files when running `{appd} tendermint show-*` subcommands ## [v0.40.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.1) - 2021-01-19 diff --git a/server/tm_cmds.go b/server/tm_cmds.go index b05a88f797da..854d4597fee8 100644 --- a/server/tm_cmds.go +++ b/server/tm_cmds.go @@ -28,7 +28,7 @@ func ShowNodeIDCmd() *cobra.Command { serverCtx := GetServerContextFromCmd(cmd) cfg := serverCtx.Config - nodeKey, err := p2p.LoadOrGenNodeKey(cfg.NodeKeyFile()) + nodeKey, err := p2p.LoadNodeKey(cfg.NodeKeyFile()) if err != nil { return err } @@ -48,7 +48,7 @@ func ShowValidatorCmd() *cobra.Command { serverCtx := GetServerContextFromCmd(cmd) cfg := serverCtx.Config - privValidator := pvm.LoadOrGenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()) + privValidator := pvm.LoadFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()) valPubKey, err := privValidator.GetPubKey() if err != nil { return err @@ -86,7 +86,7 @@ func ShowAddressCmd() *cobra.Command { serverCtx := GetServerContextFromCmd(cmd) cfg := serverCtx.Config - privValidator := pvm.LoadOrGenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()) + privValidator := pvm.LoadFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()) valConsAddr := (sdk.ConsAddress)(privValidator.GetAddress()) output, _ := cmd.Flags().GetString(cli.OutputFlag) From d37c590e90cff8e04592bf8b2c63f31f4191a3b3 Mon Sep 17 00:00:00 2001 From: Andrei Ivasko Date: Wed, 3 Feb 2021 01:47:25 -0800 Subject: [PATCH 097/152] Limit context background (#8093) * limit context background * update * fixed minor issues * fixed TestStatusCommand * Fix keyring import from older versions. (#8436) Co-authored-by: Alessio Treglia Co-authored-by: sahith-narahari * Add changelog (#8490) * fix: tendermint subcommands should not create missing files (#8481) If the user specifies an incorrect `--home`, then the old behaviour would automatically populate it with fresh values, but we should fail instead. * limit context background * update * fixed minor issues * fixed TestStatusCommand * statik.go * replaced static.go Co-authored-by: Jonathan Gimeno Co-authored-by: Alessio Treglia Co-authored-by: sahith-narahari Co-authored-by: Michael FIG --- client/cmd_test.go | 3 +- client/grpc/tmservice/block.go | 4 +- client/grpc/tmservice/service.go | 18 ++++----- client/grpc/tmservice/status.go | 4 +- client/keys/parse.go | 3 +- client/rpc/validators.go | 10 ++--- x/auth/client/cli/query.go | 5 +-- x/bank/client/cli/query.go | 13 +++---- x/bank/client/testutil/cli_helpers.go | 3 +- x/distribution/client/cli/query.go | 16 ++++---- x/distribution/client/cli/tx.go | 3 +- x/gov/client/cli/query.go | 39 +++++++++++-------- .../applications/transfer/client/cli/query.go | 7 ++-- x/ibc/core/02-client/client/cli/query.go | 7 ++-- x/ibc/core/03-connection/client/cli/query.go | 3 +- x/ibc/core/04-channel/client/cli/query.go | 11 +++--- x/mint/client/cli/query.go | 7 ++-- x/params/client/cli/query.go | 4 +- x/slashing/client/cli/query.go | 7 ++-- x/staking/client/cli/query.go | 27 +++++++------ x/upgrade/client/cli/query.go | 9 ++--- 21 files changed, 96 insertions(+), 107 deletions(-) diff --git a/client/cmd_test.go b/client/cmd_test.go index 02e2c414f63a..65161fe4752b 100644 --- a/client/cmd_test.go +++ b/client/cmd_test.go @@ -97,8 +97,7 @@ func TestSetCmdClientContextHandler(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { - ctx := context.Background() - ctx = context.WithValue(ctx, client.ClientContextKey, &client.Context{}) + ctx := context.WithValue(context.Background(), client.ClientContextKey, &client.Context{}) cmd := newCmd() _ = testutil.ApplyMockIODiscardOutErr(cmd) diff --git a/client/grpc/tmservice/block.go b/client/grpc/tmservice/block.go index e92fbec72bd2..554156982dda 100644 --- a/client/grpc/tmservice/block.go +++ b/client/grpc/tmservice/block.go @@ -8,12 +8,12 @@ import ( "github.com/cosmos/cosmos-sdk/client" ) -func getBlock(clientCtx client.Context, height *int64) (*ctypes.ResultBlock, error) { +func getBlock(ctx context.Context, clientCtx client.Context, height *int64) (*ctypes.ResultBlock, error) { // get the node node, err := clientCtx.GetNode() if err != nil { return nil, err } - return node.Block(context.Background(), height) + return node.Block(ctx, height) } diff --git a/client/grpc/tmservice/service.go b/client/grpc/tmservice/service.go index 58d44af579cc..b621dff570c2 100644 --- a/client/grpc/tmservice/service.go +++ b/client/grpc/tmservice/service.go @@ -34,8 +34,8 @@ func NewQueryServer(clientCtx client.Context, interfaceRegistry codectypes.Inter } // GetSyncing implements ServiceServer.GetSyncing -func (s queryServer) GetSyncing(_ context.Context, _ *GetSyncingRequest) (*GetSyncingResponse, error) { - status, err := getNodeStatus(s.clientCtx) +func (s queryServer) GetSyncing(ctx context.Context, _ *GetSyncingRequest) (*GetSyncingResponse, error) { + status, err := getNodeStatus(ctx, s.clientCtx) if err != nil { return nil, err } @@ -45,8 +45,8 @@ func (s queryServer) GetSyncing(_ context.Context, _ *GetSyncingRequest) (*GetSy } // GetLatestBlock implements ServiceServer.GetLatestBlock -func (s queryServer) GetLatestBlock(context.Context, *GetLatestBlockRequest) (*GetLatestBlockResponse, error) { - status, err := getBlock(s.clientCtx, nil) +func (s queryServer) GetLatestBlock(ctx context.Context, _ *GetLatestBlockRequest) (*GetLatestBlockResponse, error) { + status, err := getBlock(ctx, s.clientCtx, nil) if err != nil { return nil, err } @@ -64,7 +64,7 @@ func (s queryServer) GetLatestBlock(context.Context, *GetLatestBlockRequest) (*G } // GetBlockByHeight implements ServiceServer.GetBlockByHeight -func (s queryServer) GetBlockByHeight(_ context.Context, req *GetBlockByHeightRequest) (*GetBlockByHeightResponse, error) { +func (s queryServer) GetBlockByHeight(ctx context.Context, req *GetBlockByHeightRequest) (*GetBlockByHeightResponse, error) { chainHeight, err := rpc.GetChainHeight(s.clientCtx) if err != nil { return nil, err @@ -74,7 +74,7 @@ func (s queryServer) GetBlockByHeight(_ context.Context, req *GetBlockByHeightRe return nil, status.Error(codes.InvalidArgument, "requested block height is bigger then the chain length") } - res, err := getBlock(s.clientCtx, &req.Height) + res, err := getBlock(ctx, s.clientCtx, &req.Height) if err != nil { return nil, err } @@ -96,7 +96,7 @@ func (s queryServer) GetLatestValidatorSet(ctx context.Context, req *GetLatestVa return nil, err } - validatorsRes, err := rpc.GetValidators(s.clientCtx, nil, &page, &limit) + validatorsRes, err := rpc.GetValidators(ctx, s.clientCtx, nil, &page, &limit) if err != nil { return nil, err } @@ -147,7 +147,7 @@ func (s queryServer) GetValidatorSetByHeight(ctx context.Context, req *GetValida return nil, status.Error(codes.InvalidArgument, "requested block height is bigger then the chain length") } - validatorsRes, err := rpc.GetValidators(s.clientCtx, &req.Height, &page, &limit) + validatorsRes, err := rpc.GetValidators(ctx, s.clientCtx, &req.Height, &page, &limit) if err != nil { return nil, err @@ -175,7 +175,7 @@ func (s queryServer) GetValidatorSetByHeight(ctx context.Context, req *GetValida // GetNodeInfo implements ServiceServer.GetNodeInfo func (s queryServer) GetNodeInfo(ctx context.Context, req *GetNodeInfoRequest) (*GetNodeInfoResponse, error) { - status, err := getNodeStatus(s.clientCtx) + status, err := getNodeStatus(ctx, s.clientCtx) if err != nil { return nil, err } diff --git a/client/grpc/tmservice/status.go b/client/grpc/tmservice/status.go index f1a8da8e8362..9e9c3d200943 100644 --- a/client/grpc/tmservice/status.go +++ b/client/grpc/tmservice/status.go @@ -8,10 +8,10 @@ import ( "github.com/cosmos/cosmos-sdk/client" ) -func getNodeStatus(clientCtx client.Context) (*ctypes.ResultStatus, error) { +func getNodeStatus(ctx context.Context, clientCtx client.Context) (*ctypes.ResultStatus, error) { node, err := clientCtx.GetNode() if err != nil { return &ctypes.ResultStatus{}, err } - return node.Status(context.Background()) + return node.Status(ctx) } diff --git a/client/keys/parse.go b/client/keys/parse.go index 2af792c03c8e..b1169d68cc0e 100644 --- a/client/keys/parse.go +++ b/client/keys/parse.go @@ -1,7 +1,6 @@ package keys import ( - "context" "encoding/hex" "errors" "fmt" @@ -86,7 +85,7 @@ hexadecimal into bech32 cosmos prefixed format and vice versa. } func parseKey(cmd *cobra.Command, args []string) error { - config, _ := sdk.GetSealedConfig(context.Background()) + config, _ := sdk.GetSealedConfig(cmd.Context()) return doParseKey(cmd, config, args) } diff --git a/client/rpc/validators.go b/client/rpc/validators.go index 66c594966ed7..175e7ff91ee6 100644 --- a/client/rpc/validators.go +++ b/client/rpc/validators.go @@ -50,7 +50,7 @@ func ValidatorCommand() *cobra.Command { page, _ := cmd.Flags().GetInt(flags.FlagPage) limit, _ := cmd.Flags().GetInt(flags.FlagLimit) - result, err := GetValidators(clientCtx, height, &page, &limit) + result, err := GetValidators(cmd.Context(), clientCtx, height, &page, &limit) if err != nil { return err } @@ -117,14 +117,14 @@ func validatorOutput(validator *tmtypes.Validator) (ValidatorOutput, error) { } // GetValidators from client -func GetValidators(clientCtx client.Context, height *int64, page, limit *int) (ResultValidatorsOutput, error) { +func GetValidators(ctx context.Context, clientCtx client.Context, height *int64, page, limit *int) (ResultValidatorsOutput, error) { // get the node node, err := clientCtx.GetNode() if err != nil { return ResultValidatorsOutput{}, err } - validatorsRes, err := node.Validators(context.Background(), height, page, limit) + validatorsRes, err := node.Validators(ctx, height, page, limit) if err != nil { return ResultValidatorsOutput{}, err } @@ -172,7 +172,7 @@ func ValidatorSetRequestHandlerFn(clientCtx client.Context) http.HandlerFunc { return } - output, err := GetValidators(clientCtx, &height, &page, &limit) + output, err := GetValidators(r.Context(), clientCtx, &height, &page, &limit) if rest.CheckInternalServerError(w, err) { return } @@ -189,7 +189,7 @@ func LatestValidatorSetRequestHandlerFn(clientCtx client.Context) http.HandlerFu return } - output, err := GetValidators(clientCtx, nil, &page, &limit) + output, err := GetValidators(r.Context(), clientCtx, nil, &page, &limit) if rest.CheckInternalServerError(w, err) { return } diff --git a/x/auth/client/cli/query.go b/x/auth/client/cli/query.go index 2590858b4c20..a236e900fbe5 100644 --- a/x/auth/client/cli/query.go +++ b/x/auth/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "strings" @@ -58,7 +57,7 @@ $ query auth params } queryClient := types.NewQueryClient(clientCtx) - res, err := queryClient.Params(context.Background(), &types.QueryParamsRequest{}) + res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) if err != nil { return err } @@ -90,7 +89,7 @@ func GetAccountCmd() *cobra.Command { } queryClient := types.NewQueryClient(clientCtx) - res, err := queryClient.Account(context.Background(), &types.QueryAccountRequest{Address: key.String()}) + res, err := queryClient.Account(cmd.Context(), &types.QueryAccountRequest{Address: key.String()}) if err != nil { return err } diff --git a/x/bank/client/cli/query.go b/x/bank/client/cli/query.go index fbb9ba43825d..a192c8deba1b 100644 --- a/x/bank/client/cli/query.go +++ b/x/bank/client/cli/query.go @@ -74,11 +74,10 @@ Example: if err != nil { return err } - + ctx := cmd.Context() if denom == "" { params := types.NewQueryAllBalancesRequest(addr, pageReq) - - res, err := queryClient.AllBalances(cmd.Context(), params) + res, err := queryClient.AllBalances(ctx, params) if err != nil { return err } @@ -86,7 +85,7 @@ Example: } params := types.NewQueryBalanceRequest(addr, denom) - res, err := queryClient.Balance(cmd.Context(), params) + res, err := queryClient.Balance(ctx, params) if err != nil { return err } @@ -183,9 +182,9 @@ To query for the total supply of a specific coin denomination use: } queryClient := types.NewQueryClient(clientCtx) - + ctx := cmd.Context() if denom == "" { - res, err := queryClient.TotalSupply(cmd.Context(), &types.QueryTotalSupplyRequest{}) + res, err := queryClient.TotalSupply(ctx, &types.QueryTotalSupplyRequest{}) if err != nil { return err } @@ -193,7 +192,7 @@ To query for the total supply of a specific coin denomination use: return clientCtx.PrintProto(res) } - res, err := queryClient.SupplyOf(cmd.Context(), &types.QuerySupplyOfRequest{Denom: denom}) + res, err := queryClient.SupplyOf(ctx, &types.QuerySupplyOfRequest{Denom: denom}) if err != nil { return err } diff --git a/x/bank/client/testutil/cli_helpers.go b/x/bank/client/testutil/cli_helpers.go index 0f1b848cb755..e36f3744a6b9 100644 --- a/x/bank/client/testutil/cli_helpers.go +++ b/x/bank/client/testutil/cli_helpers.go @@ -1,7 +1,6 @@ package testutil import ( - "context" "fmt" "github.com/spf13/cobra" @@ -59,7 +58,7 @@ ignored as it is implied from [from_key_or_address].`, msg := types.NewMsgSend(clientCtx.GetFromAddress(), toAddr, coins) svcMsgClientConn := &msgservice.ServiceMsgClientConn{} bankMsgClient := types.NewMsgClient(svcMsgClientConn) - _, err = bankMsgClient.Send(context.Background(), msg) + _, err = bankMsgClient.Send(cmd.Context(), msg) if err != nil { return err } diff --git a/x/distribution/client/cli/query.go b/x/distribution/client/cli/query.go index 3b6032ce7b99..aa087f5f8b27 100644 --- a/x/distribution/client/cli/query.go +++ b/x/distribution/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "strconv" "strings" @@ -50,7 +49,7 @@ func GetCmdQueryParams() *cobra.Command { } queryClient := types.NewQueryClient(clientCtx) - res, err := queryClient.Params(context.Background(), &types.QueryParamsRequest{}) + res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) if err != nil { return err } @@ -94,7 +93,7 @@ $ %s query distribution validator-outstanding-rewards %s1lwjmdnks33xwnmfayc64ycp } res, err := queryClient.ValidatorOutstandingRewards( - context.Background(), + cmd.Context(), &types.QueryValidatorOutstandingRewardsRequest{ValidatorAddress: validatorAddr.String()}, ) if err != nil { @@ -139,7 +138,7 @@ $ %s query distribution commission %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj } res, err := queryClient.ValidatorCommission( - context.Background(), + cmd.Context(), &types.QueryValidatorCommissionRequest{ValidatorAddress: validatorAddr.String()}, ) if err != nil { @@ -199,7 +198,7 @@ $ %s query distribution slashes %svaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj } res, err := queryClient.ValidatorSlashes( - context.Background(), + cmd.Context(), &types.QueryValidatorSlashesRequest{ ValidatorAddress: validatorAddr.String(), StartingHeight: startHeight, @@ -252,6 +251,7 @@ $ %s query distribution rewards %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1ggh } // query for rewards from a particular delegation + ctx := cmd.Context() if len(args) == 2 { validatorAddr, err := sdk.ValAddressFromBech32(args[1]) if err != nil { @@ -259,7 +259,7 @@ $ %s query distribution rewards %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1ggh } res, err := queryClient.DelegationRewards( - context.Background(), + ctx, &types.QueryDelegationRewardsRequest{DelegatorAddress: delegatorAddr.String(), ValidatorAddress: validatorAddr.String()}, ) if err != nil { @@ -270,7 +270,7 @@ $ %s query distribution rewards %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1ggh } res, err := queryClient.DelegationTotalRewards( - context.Background(), + ctx, &types.QueryDelegationTotalRewardsRequest{DelegatorAddress: delegatorAddr.String()}, ) if err != nil { @@ -307,7 +307,7 @@ $ %s query distribution community-pool } queryClient := types.NewQueryClient(clientCtx) - res, err := queryClient.CommunityPool(context.Background(), &types.QueryCommunityPoolRequest{}) + res, err := queryClient.CommunityPool(cmd.Context(), &types.QueryCommunityPoolRequest{}) if err != nil { return err } diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go index d62bcd21fa07..dcf5a3b057ad 100644 --- a/x/distribution/client/cli/tx.go +++ b/x/distribution/client/cli/tx.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "strings" @@ -155,7 +154,7 @@ $ %s tx distribution withdraw-all-rewards --from mykey } queryClient := types.NewQueryClient(clientCtx) - delValsRes, err := queryClient.DelegatorValidators(context.Background(), &types.QueryDelegatorValidatorsRequest{DelegatorAddress: delAddr.String()}) + delValsRes, err := queryClient.DelegatorValidators(cmd.Context(), &types.QueryDelegatorValidatorsRequest{DelegatorAddress: delAddr.String()}) if err != nil { return err } diff --git a/x/gov/client/cli/query.go b/x/gov/client/cli/query.go index 8c67cd96e5e1..b382f540e26b 100644 --- a/x/gov/client/cli/query.go +++ b/x/gov/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "strconv" "strings" @@ -74,7 +73,7 @@ $ %s query gov proposal 1 // Query the proposal res, err := queryClient.Proposal( - context.Background(), + cmd.Context(), &types.QueryProposalRequest{ProposalId: proposalID}, ) if err != nil { @@ -149,7 +148,7 @@ $ %s query gov proposals --page=2 --limit=100 } res, err := queryClient.Proposals( - context.Background(), + cmd.Context(), &types.QueryProposalsRequest{ ProposalStatus: proposalStatus, Voter: bechVoterAddr, @@ -208,8 +207,9 @@ $ %s query gov vote 1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk } // check to see if the proposal is in the store + ctx := cmd.Context() _, err = queryClient.Proposal( - context.Background(), + ctx, &types.QueryProposalRequest{ProposalId: proposalID}, ) if err != nil { @@ -222,7 +222,7 @@ $ %s query gov vote 1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk } res, err := queryClient.Vote( - context.Background(), + ctx, &types.QueryVoteRequest{ProposalId: proposalID, Voter: args[1]}, ) if err != nil { @@ -282,8 +282,9 @@ $ %[1]s query gov votes 1 --page=2 --limit=100 } // check to see if the proposal is in the store + ctx := cmd.Context() proposalRes, err := queryClient.Proposal( - context.Background(), + ctx, &types.QueryProposalRequest{ProposalId: proposalID}, ) if err != nil { @@ -315,7 +316,7 @@ $ %[1]s query gov votes 1 --page=2 --limit=100 } res, err := queryClient.Votes( - context.Background(), + ctx, &types.QueryVotesRequest{ProposalId: proposalID, Pagination: pageReq}, ) @@ -364,8 +365,9 @@ $ %s query gov deposit 1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk } // check to see if the proposal is in the store + ctx := cmd.Context() _, err = queryClient.Proposal( - context.Background(), + ctx, &types.QueryProposalRequest{ProposalId: proposalID}, ) if err != nil { @@ -378,7 +380,7 @@ $ %s query gov deposit 1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk } res, err := queryClient.Deposit( - context.Background(), + ctx, &types.QueryDepositRequest{ProposalId: proposalID, Depositor: args[1]}, ) if err != nil { @@ -434,8 +436,9 @@ $ %s query gov deposits 1 } // check to see if the proposal is in the store + ctx := cmd.Context() proposalRes, err := queryClient.Proposal( - context.Background(), + ctx, &types.QueryProposalRequest{ProposalId: proposalID}, ) if err != nil { @@ -464,7 +467,7 @@ $ %s query gov deposits 1 } res, err := queryClient.Deposits( - context.Background(), + ctx, &types.QueryDepositsRequest{ProposalId: proposalID, Pagination: pageReq}, ) @@ -512,8 +515,9 @@ $ %s query gov tally 1 } // check to see if the proposal is in the store + ctx := cmd.Context() _, err = queryClient.Proposal( - context.Background(), + ctx, &types.QueryProposalRequest{ProposalId: proposalID}, ) if err != nil { @@ -522,7 +526,7 @@ $ %s query gov tally 1 // Query store res, err := queryClient.TallyResult( - context.Background(), + ctx, &types.QueryTallyResultRequest{ProposalId: proposalID}, ) if err != nil { @@ -561,8 +565,9 @@ $ %s query gov params queryClient := types.NewQueryClient(clientCtx) // Query store for all 3 params + ctx := cmd.Context() votingRes, err := queryClient.Params( - context.Background(), + ctx, &types.QueryParamsRequest{ParamsType: "voting"}, ) if err != nil { @@ -570,7 +575,7 @@ $ %s query gov params } tallyRes, err := queryClient.Params( - context.Background(), + ctx, &types.QueryParamsRequest{ParamsType: "tallying"}, ) if err != nil { @@ -578,7 +583,7 @@ $ %s query gov params } depositRes, err := queryClient.Params( - context.Background(), + ctx, &types.QueryParamsRequest{ParamsType: "deposit"}, ) if err != nil { @@ -626,7 +631,7 @@ $ %s query gov param deposit // Query store res, err := queryClient.Params( - context.Background(), + cmd.Context(), &types.QueryParamsRequest{ParamsType: args[0]}, ) if err != nil { diff --git a/x/ibc/applications/transfer/client/cli/query.go b/x/ibc/applications/transfer/client/cli/query.go index 7d281bb4155f..b9658e05ae92 100644 --- a/x/ibc/applications/transfer/client/cli/query.go +++ b/x/ibc/applications/transfer/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "github.com/spf13/cobra" @@ -31,7 +30,7 @@ func GetCmdQueryDenomTrace() *cobra.Command { Hash: args[0], } - res, err := queryClient.DenomTrace(context.Background(), req) + res, err := queryClient.DenomTrace(cmd.Context(), req) if err != nil { return err } @@ -69,7 +68,7 @@ func GetCmdQueryDenomTraces() *cobra.Command { Pagination: pageReq, } - res, err := queryClient.DenomTraces(context.Background(), req) + res, err := queryClient.DenomTraces(cmd.Context(), req) if err != nil { return err } @@ -98,7 +97,7 @@ func GetCmdParams() *cobra.Command { } queryClient := types.NewQueryClient(clientCtx) - res, _ := queryClient.Params(context.Background(), &types.QueryParamsRequest{}) + res, _ := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) return clientCtx.PrintProto(res.Params) }, } diff --git a/x/ibc/core/02-client/client/cli/query.go b/x/ibc/core/02-client/client/cli/query.go index 7c49b12e0220..c1b5e51a050f 100644 --- a/x/ibc/core/02-client/client/cli/query.go +++ b/x/ibc/core/02-client/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "errors" "fmt" @@ -44,7 +43,7 @@ func GetCmdQueryClientStates() *cobra.Command { Pagination: pageReq, } - res, err := queryClient.ClientStates(context.Background(), req) + res, err := queryClient.ClientStates(cmd.Context(), req) if err != nil { return err } @@ -118,7 +117,7 @@ func GetCmdQueryConsensusStates() *cobra.Command { Pagination: pageReq, } - res, err := queryClient.ConsensusStates(context.Background(), req) + res, err := queryClient.ConsensusStates(cmd.Context(), req) if err != nil { return err } @@ -250,7 +249,7 @@ func GetCmdParams() *cobra.Command { } queryClient := types.NewQueryClient(clientCtx) - res, _ := queryClient.ClientParams(context.Background(), &types.QueryClientParamsRequest{}) + res, _ := queryClient.ClientParams(cmd.Context(), &types.QueryClientParamsRequest{}) return clientCtx.PrintProto(res.Params) }, } diff --git a/x/ibc/core/03-connection/client/cli/query.go b/x/ibc/core/03-connection/client/cli/query.go index 071410398db5..21c4bd8f578e 100644 --- a/x/ibc/core/03-connection/client/cli/query.go +++ b/x/ibc/core/03-connection/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "github.com/spf13/cobra" @@ -39,7 +38,7 @@ func GetCmdQueryConnections() *cobra.Command { Pagination: pageReq, } - res, err := queryClient.Connections(context.Background(), req) + res, err := queryClient.Connections(cmd.Context(), req) if err != nil { return err } diff --git a/x/ibc/core/04-channel/client/cli/query.go b/x/ibc/core/04-channel/client/cli/query.go index 5d059c08cf94..03df474f1e79 100644 --- a/x/ibc/core/04-channel/client/cli/query.go +++ b/x/ibc/core/04-channel/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "strconv" @@ -44,7 +43,7 @@ func GetCmdQueryChannels() *cobra.Command { Pagination: pageReq, } - res, err := queryClient.Channels(context.Background(), req) + res, err := queryClient.Channels(cmd.Context(), req) if err != nil { return err } @@ -118,7 +117,7 @@ func GetCmdQueryConnectionChannels() *cobra.Command { Pagination: pageReq, } - res, err := queryClient.ConnectionChannels(context.Background(), req) + res, err := queryClient.ConnectionChannels(cmd.Context(), req) if err != nil { return err } @@ -189,7 +188,7 @@ func GetCmdQueryPacketCommitments() *cobra.Command { Pagination: pageReq, } - res, err := queryClient.PacketCommitments(context.Background(), req) + res, err := queryClient.PacketCommitments(cmd.Context(), req) if err != nil { return err } @@ -357,7 +356,7 @@ The return value represents: PacketCommitmentSequences: seqs, } - res, err := queryClient.UnreceivedPackets(context.Background(), req) + res, err := queryClient.UnreceivedPackets(cmd.Context(), req) if err != nil { return err } @@ -407,7 +406,7 @@ The return value represents: PacketAckSequences: seqs, } - res, err := queryClient.UnreceivedAcks(context.Background(), req) + res, err := queryClient.UnreceivedAcks(cmd.Context(), req) if err != nil { return err } diff --git a/x/mint/client/cli/query.go b/x/mint/client/cli/query.go index cce0d7c12bbb..792fa8a6798f 100644 --- a/x/mint/client/cli/query.go +++ b/x/mint/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "github.com/spf13/cobra" @@ -45,7 +44,7 @@ func GetCmdQueryParams() *cobra.Command { queryClient := types.NewQueryClient(clientCtx) params := &types.QueryParamsRequest{} - res, err := queryClient.Params(context.Background(), params) + res, err := queryClient.Params(cmd.Context(), params) if err != nil { return err @@ -75,7 +74,7 @@ func GetCmdQueryInflation() *cobra.Command { queryClient := types.NewQueryClient(clientCtx) params := &types.QueryInflationRequest{} - res, err := queryClient.Inflation(context.Background(), params) + res, err := queryClient.Inflation(cmd.Context(), params) if err != nil { return err @@ -105,7 +104,7 @@ func GetCmdQueryAnnualProvisions() *cobra.Command { queryClient := types.NewQueryClient(clientCtx) params := &types.QueryAnnualProvisionsRequest{} - res, err := queryClient.AnnualProvisions(context.Background(), params) + res, err := queryClient.AnnualProvisions(cmd.Context(), params) if err != nil { return err diff --git a/x/params/client/cli/query.go b/x/params/client/cli/query.go index 516ff3b6b474..ce7b45d0602d 100644 --- a/x/params/client/cli/query.go +++ b/x/params/client/cli/query.go @@ -1,8 +1,6 @@ package cli import ( - "context" - "github.com/spf13/cobra" "github.com/cosmos/cosmos-sdk/client" @@ -41,7 +39,7 @@ func NewQuerySubspaceParamsCmd() *cobra.Command { queryClient := proposal.NewQueryClient(clientCtx) params := proposal.QueryParamsRequest{Subspace: args[0], Key: args[1]} - res, err := queryClient.Params(context.Background(), ¶ms) + res, err := queryClient.Params(cmd.Context(), ¶ms) if err != nil { return err } diff --git a/x/slashing/client/cli/query.go b/x/slashing/client/cli/query.go index d55b33201b10..6cb2f803d085 100644 --- a/x/slashing/client/cli/query.go +++ b/x/slashing/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "strings" "github.com/spf13/cobra" @@ -58,7 +57,7 @@ $ query slashing signing-info cosmosvalconspub1zcjduepqfhvwcmt7p06fvdgexx consAddr := sdk.ConsAddress(pk.Address()) params := &types.QuerySigningInfoRequest{ConsAddress: consAddr.String()} - res, err := queryClient.SigningInfo(context.Background(), params) + res, err := queryClient.SigningInfo(cmd.Context(), params) if err != nil { return err } @@ -95,7 +94,7 @@ $ query slashing signing-infos } params := &types.QuerySigningInfosRequest{Pagination: pageReq} - res, err := queryClient.SigningInfos(context.Background(), params) + res, err := queryClient.SigningInfos(cmd.Context(), params) if err != nil { return err } @@ -128,7 +127,7 @@ $ query slashing params queryClient := types.NewQueryClient(clientCtx) params := &types.QueryParamsRequest{} - res, err := queryClient.Params(context.Background(), params) + res, err := queryClient.Params(cmd.Context(), params) if err != nil { return err } diff --git a/x/staking/client/cli/query.go b/x/staking/client/cli/query.go index 1e8b0a5c539a..7bf3ae41ccbe 100644 --- a/x/staking/client/cli/query.go +++ b/x/staking/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "strconv" "strings" @@ -115,7 +114,7 @@ $ %s query staking validators return err } - result, err := queryClient.Validators(context.Background(), &types.QueryValidatorsRequest{ + result, err := queryClient.Validators(cmd.Context(), &types.QueryValidatorsRequest{ // Leaving status empty on purpose to query all validators. Pagination: pageReq, }) @@ -172,7 +171,7 @@ $ %s query staking unbonding-delegations-from %s1gghjut3ccd8ay0zduzj64hwre2fxs9l Pagination: pageReq, } - res, err := queryClient.ValidatorUnbondingDelegations(context.Background(), params) + res, err := queryClient.ValidatorUnbondingDelegations(cmd.Context(), params) if err != nil { return err } @@ -227,7 +226,7 @@ $ %s query staking redelegations-from %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj Pagination: pageReq, } - res, err := queryClient.Redelegations(context.Background(), params) + res, err := queryClient.Redelegations(cmd.Context(), params) if err != nil { return err } @@ -282,7 +281,7 @@ $ %s query staking delegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1gghju ValidatorAddr: valAddr.String(), } - res, err := queryClient.Delegation(context.Background(), params) + res, err := queryClient.Delegation(cmd.Context(), params) if err != nil { return err } @@ -336,7 +335,7 @@ $ %s query staking delegations %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p Pagination: pageReq, } - res, err := queryClient.DelegatorDelegations(context.Background(), params) + res, err := queryClient.DelegatorDelegations(cmd.Context(), params) if err != nil { return err } @@ -391,7 +390,7 @@ $ %s query staking delegations-to %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj Pagination: pageReq, } - res, err := queryClient.ValidatorDelegations(context.Background(), params) + res, err := queryClient.ValidatorDelegations(cmd.Context(), params) if err != nil { return err } @@ -447,7 +446,7 @@ $ %s query staking unbonding-delegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9 ValidatorAddr: valAddr.String(), } - res, err := queryClient.UnbondingDelegation(context.Background(), params) + res, err := queryClient.UnbondingDelegation(cmd.Context(), params) if err != nil { return err } @@ -501,7 +500,7 @@ $ %s query staking unbonding-delegations %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru Pagination: pageReq, } - res, err := queryClient.DelegatorUnbondingDelegations(context.Background(), params) + res, err := queryClient.DelegatorUnbondingDelegations(cmd.Context(), params) if err != nil { return err } @@ -563,7 +562,7 @@ $ %s query staking redelegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1l2r SrcValidatorAddr: valSrcAddr.String(), } - res, err := queryClient.Redelegations(context.Background(), params) + res, err := queryClient.Redelegations(cmd.Context(), params) if err != nil { return err } @@ -617,7 +616,7 @@ $ %s query staking redelegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p Pagination: pageReq, } - res, err := queryClient.Redelegations(context.Background(), params) + res, err := queryClient.Redelegations(cmd.Context(), params) if err != nil { return err } @@ -660,7 +659,7 @@ $ %s query staking historical-info 5 } params := &types.QueryHistoricalInfoRequest{Height: height} - res, err := queryClient.HistoricalInfo(context.Background(), params) + res, err := queryClient.HistoricalInfo(cmd.Context(), params) if err != nil { return err @@ -697,7 +696,7 @@ $ %s query staking pool } queryClient := types.NewQueryClient(clientCtx) - res, err := queryClient.Pool(context.Background(), &types.QueryPoolRequest{}) + res, err := queryClient.Pool(cmd.Context(), &types.QueryPoolRequest{}) if err != nil { return err } @@ -733,7 +732,7 @@ $ %s query staking params } queryClient := types.NewQueryClient(clientCtx) - res, err := queryClient.Params(context.Background(), &types.QueryParamsRequest{}) + res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) if err != nil { return err } diff --git a/x/upgrade/client/cli/query.go b/x/upgrade/client/cli/query.go index 675dba3a9e8d..39674cbc733a 100644 --- a/x/upgrade/client/cli/query.go +++ b/x/upgrade/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "github.com/spf13/cobra" @@ -41,7 +40,7 @@ func GetCurrentPlanCmd() *cobra.Command { queryClient := types.NewQueryClient(clientCtx) params := types.QueryCurrentPlanRequest{} - res, err := queryClient.CurrentPlan(context.Background(), ¶ms) + res, err := queryClient.CurrentPlan(cmd.Context(), ¶ms) if err != nil { return err } @@ -74,9 +73,9 @@ func GetAppliedPlanCmd() *cobra.Command { return err } queryClient := types.NewQueryClient(clientCtx) - + ctx := cmd.Context() params := types.QueryAppliedPlanRequest{Name: args[0]} - res, err := queryClient.AppliedPlan(context.Background(), ¶ms) + res, err := queryClient.AppliedPlan(ctx, ¶ms) if err != nil { return err } @@ -90,7 +89,7 @@ func GetAppliedPlanCmd() *cobra.Command { if err != nil { return err } - headers, err := node.BlockchainInfo(context.Background(), res.Height, res.Height) + headers, err := node.BlockchainInfo(ctx, res.Height, res.Height) if err != nil { return err } From 2e9fd0402063a0d606dd266f9d72d275e69e95c0 Mon Sep 17 00:00:00 2001 From: SaReN Date: Wed, 3 Feb 2021 18:41:42 +0530 Subject: [PATCH 098/152] Remove Info Importer from legacy keybase (#8500) --- CHANGELOG.md | 4 ++++ crypto/keyring/legacy.go | 44 ----------------------------------- crypto/keyring/legacy_test.go | 12 ---------- 3 files changed, 4 insertions(+), 56 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73b4ff3ecd3a..12a2d94b31dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [\#8363](https://github.com/cosmos/cosmos-sdk/issues/8363) Addresses no longer have a fixed 20-byte length. From the SDK modules' point of view, any 1-255 bytes-long byte array is a valid address. +### API Breaking Changes + +* (client/keys) [\#8500](https://github.com/cosmos/cosmos-sdk/pull/8500) `InfoImporter` interface is removed from legacy keybase. + ### State Machine Breaking * (x/{bank,distrib,gov,slashing,staking}) [\#8363](https://github.com/cosmos/cosmos-sdk/issues/8363) Store keys have been modified to allow for variable-length addresses. diff --git a/crypto/keyring/legacy.go b/crypto/keyring/legacy.go index 59bdc3fc5dad..d6653e956159 100644 --- a/crypto/keyring/legacy.go +++ b/crypto/keyring/legacy.go @@ -2,7 +2,6 @@ package keyring import ( "fmt" - "io" "strings" "github.com/pkg/errors" @@ -185,49 +184,6 @@ func (kb dbKeybase) Close() error { return kb.db.Close() } func infoKey(name string) []byte { return []byte(fmt.Sprintf("%s.%s", name, infoSuffix)) } -// InfoImporter is implemented by those types that want to provide functions necessary -// to migrate keys from LegacyKeybase types to Keyring types. -type InfoImporter interface { - // Import imports ASCII-armored private keys. - Import(uid string, armor string) error -} - -type keyringMigrator struct { - kr keystore -} - -func NewInfoImporter( - appName, backend, rootDir string, userInput io.Reader, opts ...Option, -) (InfoImporter, error) { - keyring, err := New(appName, backend, rootDir, userInput, opts...) - if err != nil { - return keyringMigrator{}, err - } - - kr := keyring.(keystore) - - return keyringMigrator{kr}, nil -} - -func (m keyringMigrator) Import(uid string, armor string) error { - _, err := m.kr.Key(uid) - if err == nil { - return fmt.Errorf("cannot overwrite key %q", uid) - } - - infoBytes, err := crypto.UnarmorInfoBytes(armor) - if err != nil { - return err - } - - info, err := unmarshalInfo(infoBytes) - if err != nil { - return err - } - - return m.kr.writeInfo(info) -} - // KeybaseOption overrides options for the db. type KeybaseOption func(*kbOptions) diff --git a/crypto/keyring/legacy_test.go b/crypto/keyring/legacy_test.go index 27503bdea056..d1b0dbf3e682 100644 --- a/crypto/keyring/legacy_test.go +++ b/crypto/keyring/legacy_test.go @@ -1,7 +1,6 @@ package keyring_test import ( - "io" "path/filepath" "testing" @@ -43,15 +42,4 @@ func TestLegacyKeybase(t *testing.T) { armoredInfo, err := kb.Export(keys[0].GetName()) require.NoError(t, err) require.NotEmpty(t, armoredInfo) - - importer, err := keyring.NewInfoImporter("cosmos", "memory", "", nil) - require.NoError(t, err) - err = importer.Import("test", "") - require.Error(t, err) - require.Equal(t, io.EOF, err) - require.NoError(t, importer.Import("test", armoredInfo)) - - err = importer.Import("test", armoredInfo) - require.Error(t, err) - require.Equal(t, `public key already exist in keybase`, err.Error()) } From d84942c1c030a415216f8d95e7d8037abf089d5f Mon Sep 17 00:00:00 2001 From: Amaury Date: Wed, 3 Feb 2021 21:38:23 +0100 Subject: [PATCH 099/152] Remove useless package-lock.json (#8506) --- package-lock.json | 137 ---------------------------------------------- 1 file changed, 137 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index a0da4739d2b9..000000000000 --- a/package-lock.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "requires": true, - "lockfileVersion": 1, - "dependencies": { - "@types/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/connect": { - "version": "3.4.33", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", - "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", - "requires": { - "@types/node": "*" - } - }, - "@types/express": { - "version": "4.17.6", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.6.tgz", - "integrity": "sha512-n/mr9tZI83kd4azlPG5y997C/M4DNABK9yErhFM6hKdym4kkmd9j0vtsJyjFIwfRBxtrxZtAfGZCNRIBMFLK5w==", - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "*", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.8.tgz", - "integrity": "sha512-1SJZ+R3Q/7mLkOD9ewCBDYD2k0WyZQtWYqF/2VvoNN2/uhI49J9CDN4OAm+wGMA0DbArA4ef27xl4+JwMtGggw==", - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "@types/mime": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.2.tgz", - "integrity": "sha512-4kPlzbljFcsttWEq6aBW0OZe6BDajAmyvr2xknBG92tejQnvdGtT9+kXSZ580DqpxY9qG2xeQVF9Dq0ymUTo5Q==" - }, - "@types/node": { - "version": "14.0.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.14.tgz", - "integrity": "sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ==" - }, - "@types/passport": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.3.tgz", - "integrity": "sha512-nyztuxtDPQv9utCzU0qW7Gl8BY2Dn8BKlYAFFyxKipFxjaVd96celbkLCV/tRqqBUZ+JB8If3UfgV8347DTo3Q==", - "requires": { - "@types/express": "*" - } - }, - "@types/passport-twitter": { - "version": "1.0.35", - "resolved": "https://registry.npmjs.org/@types/passport-twitter/-/passport-twitter-1.0.35.tgz", - "integrity": "sha512-7ceE/w7bvIqDPdOkPuXSDHTwwCnBW/wpn4vB98AlXieJ31nuCzjWZKWjxtyNpie8/StigN1tzF/YCRGgEh2Seg==", - "requires": { - "@types/express": "*", - "@types/passport": "*" - } - }, - "@types/qs": { - "version": "6.9.3", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.3.tgz", - "integrity": "sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA==" - }, - "@types/range-parser": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", - "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==" - }, - "@types/serve-static": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.4.tgz", - "integrity": "sha512-jTDt0o/YbpNwZbQmE/+2e+lfjJEJJR0I3OFaKQKPWkASkCoW3i6fsUnqudSMcNAfbtmADGu8f4MV4q+GqULmug==", - "requires": { - "@types/express-serve-static-core": "*", - "@types/mime": "*" - } - }, - "oauth": { - "version": "0.9.15", - "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", - "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE=" - }, - "passport-oauth1": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/passport-oauth1/-/passport-oauth1-1.1.0.tgz", - "integrity": "sha1-p96YiiEfnPRoc3cTDqdN8ycwyRg=", - "requires": { - "oauth": "0.9.x", - "passport-strategy": "1.x.x", - "utils-merge": "1.x.x" - } - }, - "passport-strategy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" - }, - "passport-twitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/passport-twitter/-/passport-twitter-1.0.4.tgz", - "integrity": "sha1-AaeZ4fdgvy3knyul+6MigvGJMtc=", - "requires": { - "passport-oauth1": "1.x.x", - "xtraverse": "0.1.x" - } - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "xmldom": { - "version": "0.1.31", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", - "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==" - }, - "xtraverse": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/xtraverse/-/xtraverse-0.1.0.tgz", - "integrity": "sha1-t0G60BjveNip0ug63gB7P3lZxzI=", - "requires": { - "xmldom": "0.1.x" - } - } - } -} From 931af4350b4967e91e0cdf2de3491901e47bfefc Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Thu, 4 Feb 2021 04:08:11 +0100 Subject: [PATCH 100/152] Finalize ADR-028 (#8398) Finalize ADR-028 * added note about Named Accounts * Update docs/architecture/adr-028-public-key-addresses.md * remove blake2b * move some paragraphs to 'Further Discussion' * move composing module accounts to a new subsectoin * adding appendix from meeting with Alan * composed addresses: use LengthPrefix before sorting --- .../adr-028-public-key-addresses.md | 318 +++++++++++++----- 1 file changed, 239 insertions(+), 79 deletions(-) diff --git a/docs/architecture/adr-028-public-key-addresses.md b/docs/architecture/adr-028-public-key-addresses.md index 00c6dddc0bdb..bacaec79cb7d 100644 --- a/docs/architecture/adr-028-public-key-addresses.md +++ b/docs/architecture/adr-028-public-key-addresses.md @@ -3,6 +3,7 @@ ## Changelog - 2020/08/18: Initial version +- 2021/01/15: Analysis and algorithm update ## Status @@ -10,42 +11,81 @@ Proposed ## Abstract -This ADR defines a canonical 20-byte address format for new public key algorithms, multisig public keys, and module -accounts using string prefixes. +This ADR defines an address format for all addressable SDK accounts. That includes: new public key algorithms, multisig public keys, and module accounts. ## Context Issue [\#3685](https://github.com/cosmos/cosmos-sdk/issues/3685) identified that public key -address spaces are currently overlapping. One initial proposal was extending the address length and -adding prefixes for different types of addresses. +address spaces are currently overlapping. We confirmed that it significantly decreases security of Cosmos SDK. + + +### Problem + +An attacker can control an input for an address generation function. This leads to a birthday attack, which significantly decreases the security space. +To overcome this, we need to separate the inputs for different kind of account types: +a security break of one account type shouldn't impact the security of other account types. + + +### Initial proposals + +One initial proposal was extending the address length and +adding prefixes for different types of addresses. @ethanfrey explained an alternate approach originally used in https://github.com/iov-one/weave: > I spent quite a bit of time thinking about this issue while building weave... The other cosmos Sdk. - > Basically I define a condition to be a type and format as human readable string with some binary data appended. This condition is hashed into an Address (again at 20 bytes). The use of this prefix makes it impossible to find a preimage for a given address with a different condition (eg ed25519 vs secp256k1). - > This is explained in depth here https://weave.readthedocs.io/en/latest/design/permissions.html - > And the code is here, look mainly at the top where we process conditions. https://github.com/iov-one/weave/blob/master/conditions.go And explained how this approach should be sufficiently collision resistant: -> Yeah, AFAIK, 20 bytes should be collision resistance when the preimages are unique and not malleable. A space of 2^160 would expect some collision to be likely around 2^80 elements (birthday paradox). And if you want to find a collision for some existing element in the database, it is still 2^160. 2^80 only is if all these elements are written to state. +> Yeah, AFAIK, 20 bytes should be collision resistance when the preimages are unique and not malleable. A space of 2^160 would expect some collision to be likely around 2^80 elements (birthday paradox). And if you want to find a collision for some existing element in the database, it is still 2^160. 2^80 only is if all these elements are written to state. > The good example you brought up was eg. a public key bytes being a valid public key on two algorithms supported by the codec. Meaning if either was broken, you would break accounts even if they were secured with the safer variant. This is only as the issue when no differentiating type info is present in the preimage (before hashing into an address). - > I would like to hear an argument if the 20 bytes space is an actual issue for security, as I would be happy to increase my address sizes in weave. I just figured cosmos and ethereum and bitcoin all use 20 bytes, it should be good enough. And the arguments above which made me feel it was secure. But I have not done a deeper analysis. -In discussions in [\#5694](https://github.com/cosmos/cosmos-sdk/issues/5694), we agreed to go with an -approach similar to this where essentially we take the first 20 bytes of the `sha256` hash of -the key type concatenated with the key bytes, summarized as `Sha256(KeyTypePrefix || Keybytes)[:20]`. +This led to the first proposal (which we proved to be not good enough): +we concatenate a key type with a public key, hash it and take the first 20 bytes of that hash, summarized as `sha256(keyTypePrefix || keybytes)[:20]`. + + +### Review and Discussions + +In [\#5694](https://github.com/cosmos/cosmos-sdk/issues/5694) we discussed various solutions. +We agreed that 20 bytes it's not future proof, and extending the address length is the only way to allow addresses of different types, various signature types, etc. +This disqualifies the initial proposal. + +In the issue we discussed various modifications: ++ Choice of the hash function. ++ Move the prefix out of the hash function: `keyTypePrefix + sha256(keybytes)[:20]` [post-hash-prefix-proposal]. ++ Use double hashing: `sha256(keyTypePrefix + sha256(keybytes)[:20])`. ++ Increase to keybytes hash slice from 20 byte to 32 or 40 bytes. We concluded that 32 bytes, produced by a good hash functions is future secure. + +### Requirements + ++ Support currently used tools - we don't want to break an ecosystem, or add a long adaptation period. Ref: https://github.com/cosmos/cosmos-sdk/issues/8041 ++ Try to keep the address length small - addresses are widely used in state, both as part of a key and object value. + + +### Scope + +This ADR only defines a process for the generation of address bytes. For end-user interactions with addresses (through the API, or CLI, etc.), we still use bech32 to format these addresses as strings. This ADR doesn't change that. +Using bech32 for string encoding gives us support for checksum error codes and handling of user typos. + ## Decision +We define the following account types, for which we define the address function: + +1. simple accounts: represented by a regular public key (ie: secp256k1, sr25519) +2. naive multisig: accounts composed by other addressable objects (ie: naive multisig) +3. composed accounts with a native address key (ie: bls, group module accounts) +4. module accounts: basically any accounts which cannot sign transactions and which are managed internally by modules + + ### Legacy Public Key Addresses Don't Change -`secp256k1` and multisig public keys are currently in use in existing Cosmos SDK zones. They use the following -address formats: +Currently (Jan 2021), the only officially supported SDK user accounts are `secp256k1` basic accounts and legacy amino multisig. +They are used in existing Cosmos SDK zones. They use the following address formats: - secp256k1: `ripemd160(sha256(pk_bytes))[:20]` - legacy amino multisig: `sha256(aminoCdc.Marshal(pk))[:20]` @@ -56,113 +96,233 @@ The current multisig public keys use amino serialization to generate the address those public keys and their address formatting, and call them "legacy amino" multisig public keys in protobuf. We will also create multisig public keys without amino addresses to be described below. +### Hash Function Choice -### Canonical Address Format +As in other parts of the Cosmos SDK, we will use `sha256`. -We have three types of accounts we would like to create addresses for in the future: -- regular public key addresses for new signature algorithms (ex. `sr25519`). -- public key addresses for multisig public keys that don't use amino encoding -- module accounts: basically any accounts which cannot sign transactions and -which are managed internally by modules +### Basic Address -To address all of these use cases we propose the following basic `AddressHash` function, -based on the discussions in [\#5694](https://github.com/cosmos/cosmos-sdk/issues/5694): +We start with defining a base hash algorithm for generating addresses. Notably, it's used for accounts represented by a single key pair. For each public key schema we have to have an associated `typ` string, which we discuss in a section below. `hash` is the cryptographic hash function defined in the previous section. ```go -func AddressHash(prefix string, contents []byte) []byte { - preImage := []byte(prefix) - if len(contents) != 0 { - preImage = append(preImage, 0) - preImage = append(preImage, contents...) - } - return sha256.Sum256(preImage)[:20] +const A_LEN = 32 + +func Hash(typ string, key []byte) []byte { + return hash(hash(typ) + key)[:A_LEN] } ``` -`AddressHash` always take a string `prefix` as a starting point which should represent the -type of public key (ex. `sr25519`) or module account being used (ex. `staking` or `group`). -For public keys, the `contents` parameter is used to specify the binary contents of the public -key. For module accounts, `contents` can be left empty (for modules which don't manage "sub-accounts"), -or can be some module-specific content to specify different pools (ex. `bonded` or `not-bonded` for `staking`) -or managed accounts (ex. different accounts managed by the `group` module). +The `+` is bytes concatenation, which doesn't use any separator. -In the `preImage`, the byte value `0` is used as the separator between `prefix` and `contents`. This is a logical -choice given that `0` is an invalid value for a string character and is commonly used as a null terminator. +This algorithm is the outcome of a consultation session with a professional cryptographer. +Motivation: this algorithm keeps the address relatively small (length of the `typ` doesn't impact the length of the final address) +and it's more secure than [post-hash-prefix-proposal] (which uses the first 20 bytes of a pubkey hash, significantly reducing the address space). +Moreover the cryptographer motivated the choice of adding `typ` in the hash to protect against a switch table attack. -### Canonical Public Key Address Prefixes +We use the `address.Hash` function for generating addresses for all accounts represented by a single key: +* simple public keys: `address.Hash(keyType, pubkey)` ++ aggregated keys (eg: BLS): `address.Hash(keyType, aggregatedPubKey)` ++ modules: `address.Hash("module", moduleName)` -All public key types will have a unique protobuf message type such as: -```proto -package cosmos.crypto.sr25519; +### Composed Addresses -message PubKey { - bytes key = 1; +For simple composed accounts (like new naive multisig), we generalize the `address.Hash`. The address is constructed by recursively creating addresses for the sub accounts, sorting the addresses and composing them into a single address. It ensures that the ordering of keys doesn't impact the resulting address. + +```go +// We don't need a PubKey interface - we need anything which is addressable. +type Addressable interface { + Address() []byte +} + +func NewComposed(typ string, subaccounts []Addressable) []byte { + addresses = map(subaccounts, \a -> LengthPrefix(a.Address())) + addresses = sort(addresses) + return address.Hash(typ, addresses[0] + ... + addresses[n]) } ``` - -All protobuf messages have unique fully qualified names, in this example `cosmos.crypto.sr25519.PubKey`. -These names are derived directly from .proto files in a standardized way and used -in other places such as the type URL in `Any`s. Since there is an easy and obvious -way to get this name for every protobuf type, we can use this message name as the -key type `prefix` when creating addresses. For all basic public keys, `contents` -should just be the raw unencoded public key bytes. -Thus the canonical address for new public key types would be `AddressHash(proto.MessageName(pk), pk.Bytes)`. +The `typ` parameter should be a schema descriptor, containing all significant attributes with deterministic serialization (eg: utf8 string). +`LengthPrefix` is a function which prepends 1 byte to the address. The value of that byte is the length of the address bits before prepending. The address must be at most 255 bits long. +We are using `LengthPrefix` to eliminate conflicts - it assures, that for 2 lists of addresses: `as = {a1, a2, ..., an}` and `bs = {b1, b2, ..., bm}` such that every `bi` and `ai` is at most 255 long, `concatenate(map(as, \a -> LengthPrefix(a))) = map(bs, \b -> LengthPrefix(b))` iff `as = bs`. + +Implementation Tip: account implementations should cache addresses. -### Multisig Addresses +#### Multisig Addresses -For new multisig public keys, we define a custom address format not based on any encoding scheme -(amino or protobuf). This avoids issues with non-determinism in the encoding scheme. It also -ensures that multisig public keys which differ simply in the ordering of keys have the same -address by sorting child public keys first. +For new multisig public keys, we define the `typ` parameter not based on any encoding scheme (amino or protobuf). This avoids issues with non-determinism in the encoding scheme. + +Example: -First we define a proto message for multisig public keys: ```proto package cosmos.crypto.multisig; message PubKey { uint32 threshold = 1; - repeated google.protobuf.Any public_keys = 2; + repeated google.protobuf.Any pubkeys = 2; } ``` -We define the following `Address()` function for this public key: - -``` +```go func (multisig PubKey) Address() { - // first gather all the addresses of each nested public key - var addresses [][]byte - for key := range multisig.Keys { - addresses = append(joinedAddresses, key.Address()) + // first gather all nested pub keys + var keys []address.Addressable // cryptotypes.PubKey implements Addressable + for _, _key := range multisig.Pubkeys { + keys = append(keys, key.GetCachedValue().(cryptotypes.PubKey)) } - // then sort them in ascending order - addresses = Sort(addresses) + // form the type from the message name (cosmos.crypto.multisig.PubKey) and the threshold joined together + prefix := fmt.Sprintf("%s/%d", proto.MessageName(multisig), multisig.Threshold) - // then concatenate them together - var joinedAddresses []byte - for addr := range addresses { - joinedAddresses := append(joinedAddresses, addr...) - } + // use the Composed function defined above + return address.NewComposed(prefix, keys) +} +``` - // form the string prefix from the message name (cosmos.crypto.multisig.PubKey) and the threshold joined together - prefix := fmt.Sprintf("%s/%d", proto.MessageName(multisig), multisig.Threshold) +#### Module Account Addresses - // use the standard AddressHash function - return AddressHash(prefix, joinedAddresses) +NOTE: this section is not finalize and it's in active discussion. + +In Basic Address section we defined a module account address as: + +``` +address.Hash("module", moduleName) +``` + +We use `"module"` as a schema type for all module derived addresses. Module accounts can have sub accounts. The derivation process has a defined order: module name, submodule key, subsubmodule key. +Module account addresses are heavily used in the SDK so it makes sense to optimize the derivation process: instead of using of using `LengthPrefix` for the module name, we use a null byte (`'\x00'`) as a separator. This works, because null byte is not a part of a valid module name. + +``` +func Module(moduleName string, key []byte) []byte{ + return Hash("module", []byte(moduleName) + 0 + key) } -``` +``` + +**Example** A lending BTC pool address would be: +``` +btcPool := address.Module("lending", btc.Addrress()}) +``` + +If we want to create an address for a module account depending on more than one key, we can concatenate them: +``` +btcAtomAMM := address.Module("amm", btc.Addrress() + atom.Address()}) +``` + +We can continue the derivation process and can create an address for a submodule account. + +``` +func Submodule(address []byte, derivationKey []byte) { + return Hash("module", address + derivationKey) +} +``` + +NOTE: if `address` is not a hash based address (with `LEN` length) then we should use `LengthPrefix`. An alternative would be to use one `Module` function, which takes a slice of keys and mapped with `LengthPrefix`. For final version we need to validate what's the most common use. + + +**Example** For a cosmwasm smart-contract address we could use the following construction: +``` +smartContractAddr := Submodule(Module("cosmwasm", smartContractsNamespace), smartContractKey) +``` + + + +### Schema Types + +A `typ` parameter used in `Hash` function SHOULD be unique for each account type. +Since all SDK account types are serialized in the state, we propose to use the protobuf message name string. + +Example: all public key types have a unique protobuf message type similar to: + +```proto +package cosmos.crypto.sr25519; + +message PubKey { + bytes key = 1; +} +``` + +All protobuf messages have unique fully qualified names, in this example `cosmos.crypto.sr25519.PubKey`. +These names are derived directly from .proto files in a standardized way and used +in other places such as the type URL in `Any`s. We can easily obtain the name using +`proto.MessageName(msg)`. + + ## Consequences +### Backwards Compatibility + +This ADR is compatible with what was committed and directly supported in the SDK repository. + ### Positive -- a simple algorithm for generating addresses for new public keys and module accounts + +- a simple algorithm for generating addresses for new public keys, complex accounts and modules +- the algorithm generalizes _native composed keys_ +- increased security and collision resistance of addresses +- the approach is extensible for future use-cases - one can use other address types, as long as they don't conflict with the address length specified here (20 or 32 bytes). +- support new account types. ### Negative + - addresses do not communicate key type, a prefixed approach would have done this +- addresses are 60% longer and will consume more storage space +- requires a refactor of KVStore store keys to handle variable length addresses ### Neutral + - protobuf message names are used as key type prefixes -## References + +## Further Discussions + +Some accounts can have a fixed name or may be constructed in other way (eg: modules). We were discussing an idea of an account with a predefined name (eg: `me.regen`), which could be used by institutions. +Without going into details, these kinds of addresses are compatible with the hash based addresses described here as long as they don't have the same length. +More specifically, any special account address must not have a length equal to 20 or 32 bytes. + + +## Appendix: Consulting session + +End of Dec 2020 we had a session with [Alan Szepieniec](https://scholar.google.be/citations?user=4LyZn8oAAAAJ&hl=en) to consult the approach presented above. + +Alan general observations: ++ we don’t need 2-preimage resistance ++ we need 32bytes address space for collision resistance ++ when an attacker can control an input for object with an address then we have a problem with birthday attack ++ there is an issue with smart-contracts for hashing ++ sha2 mining can be use to breaking address pre-image + +Hashing algorithm ++ any attack breaking blake3 will break blake2 ++ Alan is pretty confident about the current security analysis of the blake hash algorithm. It was a finalist, and the author is well known in security analysis. + + +Algorithm: ++ Alan recommends to hash the prefix: `address(pub_key) = hash(hash(key_type) + pub_key)[:32]`, main benefits: + + we are free to user arbitrary long prefix names + + we still don’t risk collisions + + switch tables ++ discussion about penalization -> about adding prefix post hash ++ Aaron asked about post hash prefixes (`address(pub_key) = key_type + hash(pub_key)`) and differences. Alan noted that this approach has longer address space and it’s stronger. + +Algorithm for complex / composed keys: ++ merging tree like addresses with same algorithm are fine + +Module addresses: Should module addresses have different size to differentiate it? ++ we will need to set a pre-image prefix for module addresse to keept them in 32-byte space: `hash(hash('module') + module_key)` ++ Aaron observation: we already need to deal with variable length (to not break secp256k1 keys). + +Discssion about arithmetic hash function for ZKP ++ Posseidon / Rescue ++ Problem: much bigger risk because we don’t know much techniques and history of crypto-analysis of arithmetic constructions. It’s still a new ground and area of active research. + +Post quantum signature size ++ Alan suggestion: Falcon: speed / size ration - very good. ++ Aaron - should we think about it? + Alan: based on early extrapolation this thing will get able to break EC cryptography in 2050 . But that’s a lot of uncertainty. But there is magic happening with recurions / linking / simulation and that can speedup the progress. + +Other ideas ++ Let’s say we use same key and two different address algorithms for 2 different use cases. Is it still safe to use it? Alan: if we want to hide the public key (which is not our use case), then it’s less secure but there are fixes. + + +### References ++ [Notes](https://hackmd.io/_NGWI4xZSbKzj1BkCqyZMw) From 2e04f2778f2aa2445f4a917ed4a6535b7ce6e3fb Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 4 Feb 2021 09:54:01 +0000 Subject: [PATCH 101/152] snapshots: document use of ioutil.TempDir() (#8508) Document with inline comments the changes introduced in https://github.com/cosmos/cosmos-sdk/pull/8475. Run make format. --- server/grpc/grpc_web.go | 3 ++- snapshots/helpers_test.go | 3 +++ snapshots/store_test.go | 3 +++ x/authz/client/cli/cli_test.go | 3 ++- x/authz/keeper/keeper_test.go | 5 ++--- x/feegrant/ante/fee_test.go | 7 ++++--- x/feegrant/client/cli/cli_test.go | 7 ++++--- x/feegrant/client/cli/query.go | 3 ++- x/feegrant/client/rest/grpc_query_test.go | 3 ++- x/feegrant/genesis_test.go | 5 +++-- x/feegrant/simulation/decoder_test.go | 3 ++- x/feegrant/simulation/genesis_test.go | 3 ++- x/feegrant/types/basic_fee_test.go | 5 +++-- x/feegrant/types/expiration_test.go | 3 ++- x/feegrant/types/grant.go | 3 ++- x/feegrant/types/grant_test.go | 5 +++-- x/feegrant/types/msgs.go | 3 ++- x/feegrant/types/periodic_fee_test.go | 5 +++-- 18 files changed, 46 insertions(+), 26 deletions(-) diff --git a/server/grpc/grpc_web.go b/server/grpc/grpc_web.go index 30c71808e43e..67dc4364a80f 100644 --- a/server/grpc/grpc_web.go +++ b/server/grpc/grpc_web.go @@ -3,9 +3,10 @@ package grpc import ( "net/http" - "github.com/cosmos/cosmos-sdk/server/config" "github.com/improbable-eng/grpc-web/go/grpcweb" "google.golang.org/grpc" + + "github.com/cosmos/cosmos-sdk/server/config" ) // StartGRPCWeb starts a gRPC-Web server on the given address. diff --git a/snapshots/helpers_test.go b/snapshots/helpers_test.go index 751ac212d352..705667919146 100644 --- a/snapshots/helpers_test.go +++ b/snapshots/helpers_test.go @@ -101,6 +101,9 @@ func (m *mockSnapshotter) Snapshot(height uint64, format uint32) (<-chan io.Read // setupBusyManager creates a manager with an empty store that is busy creating a snapshot at height 1. // The snapshot will complete when the returned closer is called. func setupBusyManager(t *testing.T) *snapshots.Manager { + // ioutil.TempDir() is used instead of testing.T.TempDir() + // see https://github.com/cosmos/cosmos-sdk/pull/8475 for + // this change's rationale. tempdir, err := ioutil.TempDir("", "") require.NoError(t, err) t.Cleanup(func() { _ = os.RemoveAll(tempdir) }) diff --git a/snapshots/store_test.go b/snapshots/store_test.go index 325fd3410bea..333031bc44cd 100644 --- a/snapshots/store_test.go +++ b/snapshots/store_test.go @@ -20,6 +20,9 @@ import ( ) func setupStore(t *testing.T) *snapshots.Store { + // ioutil.TempDir() is used instead of testing.T.TempDir() + // see https://github.com/cosmos/cosmos-sdk/pull/8475 for + // this change's rationale. tempdir, err := ioutil.TempDir("", "") require.NoError(t, err) t.Cleanup(func() { _ = os.RemoveAll(tempdir) }) diff --git a/x/authz/client/cli/cli_test.go b/x/authz/client/cli/cli_test.go index fb6fb1a1774c..96f5da08bbcf 100644 --- a/x/authz/client/cli/cli_test.go +++ b/x/authz/client/cli/cli_test.go @@ -12,9 +12,10 @@ import ( "github.com/stretchr/testify/suite" + tmcli "github.com/tendermint/tendermint/libs/cli" + "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" - tmcli "github.com/tendermint/tendermint/libs/cli" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/testutil" diff --git a/x/authz/keeper/keeper_test.go b/x/authz/keeper/keeper_test.go index 5a544a04af55..43dbc3b94b5f 100644 --- a/x/authz/keeper/keeper_test.go +++ b/x/authz/keeper/keeper_test.go @@ -4,17 +4,16 @@ import ( "testing" "time" - "github.com/cosmos/cosmos-sdk/baseapp" proto "github.com/gogo/protobuf/proto" - + "github.com/stretchr/testify/suite" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmtime "github.com/tendermint/tendermint/types/time" + "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/authz/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/stretchr/testify/suite" ) type TestSuite struct { diff --git a/x/feegrant/ante/fee_test.go b/x/feegrant/ante/fee_test.go index 293f448d73f8..fe7bc4208a98 100644 --- a/x/feegrant/ante/fee_test.go +++ b/x/feegrant/ante/fee_test.go @@ -5,13 +5,14 @@ import ( "testing" "time" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/stretchr/testify/suite" "github.com/tendermint/tendermint/crypto" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/simapp/helpers" "github.com/cosmos/cosmos-sdk/testutil/testdata" diff --git a/x/feegrant/client/cli/cli_test.go b/x/feegrant/client/cli/cli_test.go index 224e7282a80a..df4ac286f7d4 100644 --- a/x/feegrant/client/cli/cli_test.go +++ b/x/feegrant/client/cli/cli_test.go @@ -6,6 +6,10 @@ import ( "fmt" "testing" + "github.com/gogo/protobuf/proto" + "github.com/stretchr/testify/suite" + tmcli "github.com/tendermint/tendermint/libs/cli" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -16,9 +20,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/feegrant/types" govtestutil "github.com/cosmos/cosmos-sdk/x/gov/client/testutil" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/gogo/protobuf/proto" - "github.com/stretchr/testify/suite" - tmcli "github.com/tendermint/tendermint/libs/cli" ) type IntegrationTestSuite struct { diff --git a/x/feegrant/client/cli/query.go b/x/feegrant/client/cli/query.go index c3a488ab5536..5fd10cd1beda 100644 --- a/x/feegrant/client/cli/query.go +++ b/x/feegrant/client/cli/query.go @@ -4,12 +4,13 @@ import ( "fmt" "strings" + "github.com/spf13/cobra" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/feegrant/types" - "github.com/spf13/cobra" ) // GetQueryCmd returns the cli query commands for this module diff --git a/x/feegrant/client/rest/grpc_query_test.go b/x/feegrant/client/rest/grpc_query_test.go index 10d77a1e4c1f..7b665ee9153b 100644 --- a/x/feegrant/client/rest/grpc_query_test.go +++ b/x/feegrant/client/rest/grpc_query_test.go @@ -4,6 +4,8 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/suite" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -14,7 +16,6 @@ import ( banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" "github.com/cosmos/cosmos-sdk/x/feegrant/client/cli" "github.com/cosmos/cosmos-sdk/x/feegrant/types" - "github.com/stretchr/testify/suite" ) type IntegrationTestSuite struct { diff --git a/x/feegrant/genesis_test.go b/x/feegrant/genesis_test.go index d086daac077f..3ea58441a8a1 100644 --- a/x/feegrant/genesis_test.go +++ b/x/feegrant/genesis_test.go @@ -3,14 +3,15 @@ package feegrant_test import ( "testing" + "github.com/stretchr/testify/suite" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" feegrant "github.com/cosmos/cosmos-sdk/x/feegrant" "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" "github.com/cosmos/cosmos-sdk/x/feegrant/types" - "github.com/stretchr/testify/suite" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) type GenesisTestSuite struct { diff --git a/x/feegrant/simulation/decoder_test.go b/x/feegrant/simulation/decoder_test.go index 0087e5eba117..887111845636 100644 --- a/x/feegrant/simulation/decoder_test.go +++ b/x/feegrant/simulation/decoder_test.go @@ -4,13 +4,14 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/kv" "github.com/cosmos/cosmos-sdk/x/feegrant/simulation" "github.com/cosmos/cosmos-sdk/x/feegrant/types" - "github.com/stretchr/testify/require" ) var ( diff --git a/x/feegrant/simulation/genesis_test.go b/x/feegrant/simulation/genesis_test.go index 4f3ae74b56be..3d00ba3ecec3 100644 --- a/x/feegrant/simulation/genesis_test.go +++ b/x/feegrant/simulation/genesis_test.go @@ -5,13 +5,14 @@ import ( "math/rand" "testing" + "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/feegrant/simulation" "github.com/cosmos/cosmos-sdk/x/feegrant/types" - "github.com/stretchr/testify/require" ) func TestRandomizedGenState(t *testing.T) { diff --git a/x/feegrant/types/basic_fee_test.go b/x/feegrant/types/basic_fee_test.go index a5669e99ada4..dd3f09590f8a 100644 --- a/x/feegrant/types/basic_fee_test.go +++ b/x/feegrant/types/basic_fee_test.go @@ -4,10 +4,11 @@ import ( "testing" "time" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/feegrant/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" ) func TestBasicFeeValidAllow(t *testing.T) { diff --git a/x/feegrant/types/expiration_test.go b/x/feegrant/types/expiration_test.go index 60b1753bcbc1..5f390c328a8b 100644 --- a/x/feegrant/types/expiration_test.go +++ b/x/feegrant/types/expiration_test.go @@ -4,9 +4,10 @@ import ( "testing" "time" - "github.com/cosmos/cosmos-sdk/x/feegrant/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/x/feegrant/types" ) func TestExpiresAt(t *testing.T) { diff --git a/x/feegrant/types/grant.go b/x/feegrant/types/grant.go index ca2c93d9efb2..97a18de52952 100644 --- a/x/feegrant/types/grant.go +++ b/x/feegrant/types/grant.go @@ -3,10 +3,11 @@ package types import ( "time" + proto "github.com/gogo/protobuf/proto" + "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - proto "github.com/gogo/protobuf/proto" ) var ( diff --git a/x/feegrant/types/grant_test.go b/x/feegrant/types/grant_test.go index a4819b102cb2..8b29d47ee079 100644 --- a/x/feegrant/types/grant_test.go +++ b/x/feegrant/types/grant_test.go @@ -3,11 +3,12 @@ package types_test import ( "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/feegrant/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestGrant(t *testing.T) { diff --git a/x/feegrant/types/msgs.go b/x/feegrant/types/msgs.go index 5a25016f87e0..04f09c8f3fd5 100644 --- a/x/feegrant/types/msgs.go +++ b/x/feegrant/types/msgs.go @@ -1,10 +1,11 @@ package types import ( + "github.com/gogo/protobuf/proto" + "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/gogo/protobuf/proto" ) var ( diff --git a/x/feegrant/types/periodic_fee_test.go b/x/feegrant/types/periodic_fee_test.go index cc54f4080878..229fd99cea96 100644 --- a/x/feegrant/types/periodic_fee_test.go +++ b/x/feegrant/types/periodic_fee_test.go @@ -4,10 +4,11 @@ import ( "testing" "time" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/feegrant/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" ) func TestPeriodicFeeValidAllow(t *testing.T) { From 0ddb7041a8df1c61a4972174194309f8dc459bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Fran=C3=A7a=20Ferreira?= Date: Thu, 4 Feb 2021 06:58:27 -0300 Subject: [PATCH 102/152] fixing typo at 'os' backend session (#8477) Co-authored-by: SaReN Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/run-node/keyring.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/run-node/keyring.md b/docs/run-node/keyring.md index e84a4d07181b..61636f27fd47 100644 --- a/docs/run-node/keyring.md +++ b/docs/run-node/keyring.md @@ -31,7 +31,7 @@ is a list of the most popular operating systems and their respective passwords m GNU/Linux distributions that use GNOME as default desktop environment typically come with [Seahorse](https://wiki.gnome.org/Apps/Seahorse). Users of KDE based distributions are commonly provided with [KDE Wallet Manager](https://userbase.kde.org/KDE_Wallet_Manager). -Whilst the former is in fact a `libsecret` convenient frontend, the former is a `kwallet` +Whilst the former is in fact a `libsecret` convenient frontend, the latter is a `kwallet` client. `os` is the default option since operating system's default credentials managers are From 0af248b95b3de060d23ffb2f3ca760fd10120abc Mon Sep 17 00:00:00 2001 From: atheeshp <59333759+atheeshp@users.noreply.github.com> Date: Thu, 4 Feb 2021 19:08:16 +0530 Subject: [PATCH 103/152] Add specs for feegrant (#8496) * add specs * address review comments * Address review changes Co-authored-by: Amaury * review changes * address review changes Co-authored-by: Marie Gauthier Co-authored-by: Amaury Co-authored-by: Marie Gauthier --- x/feegrant/spec/01_concepts.md | 70 ++++++++++++++++++++++++++++++++++ x/feegrant/spec/02_state.md | 15 ++++++++ x/feegrant/spec/03_messages.md | 17 +++++++++ x/feegrant/spec/04_events.md | 33 ++++++++++++++++ x/feegrant/spec/README.md | 32 ++++++++++++++++ 5 files changed, 167 insertions(+) create mode 100644 x/feegrant/spec/01_concepts.md create mode 100644 x/feegrant/spec/02_state.md create mode 100644 x/feegrant/spec/03_messages.md create mode 100644 x/feegrant/spec/04_events.md create mode 100644 x/feegrant/spec/README.md diff --git a/x/feegrant/spec/01_concepts.md b/x/feegrant/spec/01_concepts.md new file mode 100644 index 000000000000..92200f2d4797 --- /dev/null +++ b/x/feegrant/spec/01_concepts.md @@ -0,0 +1,70 @@ + + +# Concepts + +## FeeAllowanceGrant + +`FeeAllowanceGrant` is stored in the KVStore to record a grant with full context. Every grant will contain `granter`, `grantee` and what kind of `allowance` is granted. `granter` is an account address who is giving permission to `grantee` (the beneficiary account address) to pay for some or all of `grantee`'s transaction fees. `allowance` defines what kind of fee allowance (`BasicFeeAllowance` or `PeriodicFeeAllowance`, see below) is granted to `grantee`. `allowance` accepts an interface which implements `FeeAllowanceI`, encoded as `Any` type. There can be only one existing fee grant allowed for a `grantee` and `granter`, self grants are not allowed. + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/proto/cosmos/feegrant/v1beta1/feegrant.proto#L75-L81 + +`FeeAllowanceI` looks like: + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/x/feegrant/types/fees.go#L9-L32 + +## Fee Allowance types +There are two types of fee allowances present at the moment: +- `BasicFeeAllowance` +- `PeriodicFeeAllowance` + +## BasicFeeAllowance + +`BasicFeeAllowance` is permission for `grantee` to use fee from a `granter`'s account. If any of the `spend_limit` or `expiration` reaches its limit, the grant will be removed from the state. + + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/proto/cosmos/feegrant/v1beta1/feegrant.proto#L13-L26 + +- `spend_limit` is the limit of coins that are allowed to be used from the `granter` account. If it is empty, it assumes there's no spend limit, `grantee` can use any number of available tokens from `granter` account address before the expiration. + +- `expiration` specifies an optional time when this allowance expires. If the value is left empty, there is no expiry for the grant. + +- When a grant is created with empty values for `spend_limit` and `expiration`, it is still a valid grant. It won't restrict the `grantee` to use any number of tokens from `granter` and it won't have any expiration. The only way to restrict the `grantee` is by revoking the grant. + +## PeriodicFeeAllowance + +`PeriodicFeeAllowance` is a repeating fee allowance for the mentioned period, we can mention when the grant can expire as well as when a period can reset. We can also define the maximum number of coins that can be used in a mentioned period of time. + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/proto/cosmos/feegrant/v1beta1/feegrant.proto#L28-L73 + +- `basic` is the instance of `BasicFeeAllowance` which is optional for periodic fee allowance. If empty, the grant will have no `expiration` and no `spend_limit`. + +- `period` is the specific period of time or blocks, after each period passes, `period_spend_limit` will be reset. + +- `period_spend_limit` specifies the maximum number of coins that can be spent in the period. + +- `period_can_spend` is the number of coins left to be spent before the period_reset time. + +- `period_reset` keeps track of when a next period reset should happen. + +## FeeAccount flag + +`feegrant` module introduces a `FeeAccount` flag for CLI for the sake of executing transactions with fee granter. When this flag is set, `clientCtx` will append the granter account address for transactions generated through CLI. + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/client/cmd.go#L224-L235 + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/client/tx/tx.go#L120 + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/x/auth/tx/builder.go#L268-L277 + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/proto/cosmos/tx/v1beta1/tx.proto#L160-L181 + +Example cmd: +```go +./simd tx gov submit-proposal --title="Test Proposal" --description="My awesome proposal" --type="Text" --from validator-key --fee-account=cosmos1xh44hxt7spr67hqaa7nyx5gnutrz5fraw6grxn --chain-id=testnet --fees="10stake" +``` + +## DeductGrantedFeeDecorator + +`feegrant` module also adds a `DeductGrantedFeeDecorator` ante handler. Whenever a transaction is being executed with `granter` field set, then this ante handler will check whether `payer` and `granter` have proper fee allowance grant in state. If it exists the fees will be deducted from the `granter`'s account address. If the `granter` field isn't set then this ante handler works as normal fee deductor. diff --git a/x/feegrant/spec/02_state.md b/x/feegrant/spec/02_state.md new file mode 100644 index 000000000000..463ea70d0685 --- /dev/null +++ b/x/feegrant/spec/02_state.md @@ -0,0 +1,15 @@ + + +# State + +## FeeAllowance + +Fee Allowances are identified by combining `Grantee` (the account address of fee allowance grantee) with the `Granter` (the account address of fee allowance granter). + +Fee allowances are stored in the state as follows: + +- FeeAllowance: `0x00 | grantee_addr_len (1 byte) | grantee_addr_bytes | granter_addr_len (1 byte) | granter_addr_bytes -> ProtocolBuffer(FeeAllowance)` + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/x/feegrant/types/feegrant.pb.go#L358-L363 diff --git a/x/feegrant/spec/03_messages.md b/x/feegrant/spec/03_messages.md new file mode 100644 index 000000000000..3ca65e25cd3f --- /dev/null +++ b/x/feegrant/spec/03_messages.md @@ -0,0 +1,17 @@ + + +# Messages + +## Msg/GrantFeeAllowance + +A fee allowance grant will be created with the `MsgGrantFeeAllowance` message. + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/proto/cosmos/feegrant/v1beta1/tx.proto#L22-L28 + +## Msg/RevokeFeeAllowance + +An allowed grant fee allowance can be removed with the `MsgRevokeFeeAllowance` message. + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/proto/cosmos/feegrant/v1beta1/tx.proto#L33-L37 diff --git a/x/feegrant/spec/04_events.md b/x/feegrant/spec/04_events.md new file mode 100644 index 000000000000..021142d3904b --- /dev/null +++ b/x/feegrant/spec/04_events.md @@ -0,0 +1,33 @@ + + +# Events + +The feegrant module emits the following events: + +# Handlers + +### MsgGrantFeeAllowance + +| Type | Attribute Key | Attribute Value | +| -------- | ------------- | ------------------ | +| message | action | set_feegrant | +| message | granter | {granterAddress} | +| message | grantee | {granteeAddress} | + +### MsgRevokeFeeAllowance + +| Type | Attribute Key | Attribute Value | +| -------- | ------------- | ------------------ | +| message | action | revoke_feegrant | +| message | granter | {granterAddress} | +| message | grantee | {granteeAddress} | + +### Exec fee allowance + +| Type | Attribute Key | Attribute Value | +| -------- | ------------- | ------------------ | +| message | action | use_feegrant | +| message | granter | {granterAddress} | +| message | grantee | {granteeAddress} | \ No newline at end of file diff --git a/x/feegrant/spec/README.md b/x/feegrant/spec/README.md new file mode 100644 index 000000000000..1abdcf464b14 --- /dev/null +++ b/x/feegrant/spec/README.md @@ -0,0 +1,32 @@ + + +## Abstract + +This document specifies the feegrant module. For the full ADR, please see [Fee Grant ADR-029](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/docs/architecture/adr-029-fee-grant-module.md). + +This module allows accounts to grant fee allowances and to use fees from their accounts. Grantees can execute any transaction without the need to maintain sufficient fees. + +## Contents + +1. **[Concepts](01_concepts.md)** + - [FeeAllowanceGrant](01_concepts.md#feeallowancegrant) + - [Fee Allowance types](01_concepts.md#fee-allowance-types) + - [BasicFeeAllowance](01_concepts.md#basicfeeallowance) + - [PeriodicFeeAllowance](01_concepts.md#periodicfeeallowance) + - [FeeAccount flag](01_concepts.md#feeaccount-flag) + - [DeductGrantedFeeDecorator](01_concepts.md#deductgrantedfeedecorator) +2. **[State](02_state.md)** + - [FeeAllowance](02_state.md#feeallowance) +3. **[Messages](03_messages.md)** + - [Msg/GrantFeeAllowance](03_messages.md#msggrantfeeallowance) + - [Msg/RevokeFeeAllowance](03_messages.md#msgrevokefeeallowance) +3. **[Events](04_events.md)** + - [MsgGrantFeeAllowance](04_events.md#msggrantfeeallowance) + - [MsgrevokeFeeAllowance](04_events.md#msgrevokefeeallowance) + - [Exec fee allowance](04_events.md#exec-fee-allowance) + From a3757e14a8f71d28975d270128b47209112fe8fa Mon Sep 17 00:00:00 2001 From: Ian Norden Date: Thu, 4 Feb 2021 20:09:28 -0600 Subject: [PATCH 104/152] ADR 038: State Listening (#8012) * ADR-038 state listening * updates/fixes * review fixes/adjustments * review fixes/adjustments part 2 * review updates part 3: refactor after review to coordinate store changes with block and tx messages and enable file pruning * review updates part 4: additional details and fixes; addressing recent feedback; use binary protobuf encoding for kv pairs in files * review updates part 5: formatting fixes; updated StreamingService/Hook interface * auxiliary streaming/queue service * review updates part 6: update StoreKVPair to differentiate between Set and Deletes on nil byte values; some minor adjustments * typo fix --- docs/architecture/README.md | 3 +- docs/architecture/adr-038-state-listening.md | 612 +++++++++++++++++++ 2 files changed, 614 insertions(+), 1 deletion(-) create mode 100644 docs/architecture/adr-038-state-listening.md diff --git a/docs/architecture/README.md b/docs/architecture/README.md index a979f30e418c..19e6d6e2db49 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -73,4 +73,5 @@ Read about the [PROCESS](./PROCESS.md). - [ADR 028: Public Key Addresses](./adr-028-public-key-addresses.md) - [ADR 032: Typed Events](./adr-032-typed-events.md) - [ADR 035: Rosetta API Support](./adr-035-rosetta-api-support.md) -- [ADR 037: Governance Split Votes](./adr-037-gov-split-vote.md) \ No newline at end of file +- [ADR 037: Governance Split Votes](./adr-037-gov-split-vote.md) +- [ADR 038: State Listening](./adr-038-state-listening.md) \ No newline at end of file diff --git a/docs/architecture/adr-038-state-listening.md b/docs/architecture/adr-038-state-listening.md new file mode 100644 index 000000000000..cd78e72e2caa --- /dev/null +++ b/docs/architecture/adr-038-state-listening.md @@ -0,0 +1,612 @@ +# ADR 038: KVStore state listening + +## Changelog + +- 11/23/2020: Initial draft + +## Status + +Proposed + +## Abstract + +This ADR defines a set of changes to enable listening to state changes of individual KVStores and exposing these data to consumers. + +## Context + +Currently, KVStore data can be remotely accessed through [Queries](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/messages-and-queries.md#queries) +which proceed either through Tendermint and the ABCI, or through the gRPC server. +In addition to these request/response queries, it would be beneficial to have a means of listening to state changes as they occur in real time. + +## Decision + +We will modify the `MultiStore` interface and its concrete (`rootmulti` and `cachemulti`) implementations and introduce a new `listenkv.Store` to allow listening to state changes in underlying KVStores. +We will also introduce the tooling for writing these state changes out to files and configuring this service. + +### Listening interface + +In a new file, `store/types/listening.go`, we will create a `WriteListener` interface for streaming out state changes from a KVStore. + +```go +// WriteListener interface for streaming data out from a listenkv.Store +type WriteListener interface { + // if value is nil then it was deleted + // storeKey indicates the source KVStore, to facilitate using the the same WriteListener across separate KVStores + // set bool indicates if it was a set; true: set, false: delete + OnWrite(storeKey types.StoreKey, set bool, key []byte, value []byte) +} +``` + +### Listener type + +We will create a concrete implementation of the `WriteListener` interface in `store/types/listening.go`, that writes out protobuf +encoded KV pairs to an underlying `io.Writer`. + +This will include defining a simple protobuf type for the KV pairs. In addition to the key and value fields this message +will include the StoreKey for the originating KVStore so that we can write out from separate KVStores to the same stream/file +and determine the source of each KV pair. + +```protobuf +message StoreKVPair { + optional string store_key = 1; // the store key for the KVStore this pair originates from + required bool set = 2; // true indicates a set operation, false indicates a delete operation + required bytes key = 3; + required bytes value = 4; +} +``` + +```go +// StoreKVPairWriteListener is used to configure listening to a KVStore by writing out length-prefixed +// protobuf encoded StoreKVPairs to an underlying io.Writer +type StoreKVPairWriteListener struct { + writer io.Writer + marshaller codec.BinaryMarshaler +} + +// NewStoreKVPairWriteListener wraps creates a StoreKVPairWriteListener with a provdied io.Writer and codec.BinaryMarshaler +func NewStoreKVPairWriteListener(w io.Writer, m codec.BinaryMarshaler) *StoreKVPairWriteListener { + return &StoreKVPairWriteListener{ + writer: w, + marshaller: m, + } +} + +// OnWrite satisfies the WriteListener interface by writing length-prefixed protobuf encoded StoreKVPairs +func (wl *StoreKVPairWriteListener) OnWrite(storeKey types.StoreKey, set bool, key []byte, value []byte) { + kvPair := new(types.StoreKVPair) + kvPair.StoreKey = storeKey.Name() + kvPair.Set = set + kvPair.Key = key + kvPair.Value = value + if by, err := wl.marshaller.MarshalBinaryLengthPrefixed(kvPair); err == nil { + wl.writer.Write(by) + } +} +``` + +### ListenKVStore + +We will create a new `Store` type `listenkv.Store` that the `MultiStore` wraps around a `KVStore` to enable state listening. +We can configure the `Store` with a set of `WriteListener`s which stream the output to specific destinations. + +```go +// Store implements the KVStore interface with listening enabled. +// Operations are traced on each core KVStore call and written to any of the +// underlying listeners with the proper key and operation permissions +type Store struct { + parent types.KVStore + listeners []types.WriteListener + parentStoreKey types.StoreKey +} + +// NewStore returns a reference to a new traceKVStore given a parent +// KVStore implementation and a buffered writer. +func NewStore(parent types.KVStore, psk types.StoreKey, listeners []types.WriteListener) *Store { + return &Store{parent: parent, listeners: listeners, parentStoreKey: psk} +} + +// Set implements the KVStore interface. It traces a write operation and +// delegates the Set call to the parent KVStore. +func (s *Store) Set(key []byte, value []byte) { + types.AssertValidKey(key) + s.parent.Set(key, value) + s.onWrite(true, key, value) +} + +// Delete implements the KVStore interface. It traces a write operation and +// delegates the Delete call to the parent KVStore. +func (s *Store) Delete(key []byte) { + s.parent.Delete(key) + s.onWrite(false, key, nil) +} + +// onWrite writes a KVStore operation to all of the WriteListeners +func (s *Store) onWrite(set bool, key, value []byte) { + for _, l := range s.listeners { + l.OnWrite(s.parentStoreKey, set, key, value) + } +} +``` + +### MultiStore interface updates + +We will update the `MultiStore` interface to allow us to wrap a set of listeners around a specific `KVStore`. +Additionally, we will update the `CacheWrap` and `CacheWrapper` interfaces to enable listening in the caching layer. + +```go +type MultiStore interface { + ... + + // ListeningEnabled returns if listening is enabled for the KVStore belonging the provided StoreKey + ListeningEnabled(key StoreKey) bool + + // SetListeners sets the WriteListeners for the KVStore belonging to the provided StoreKey + // It appends the listeners to a current set, if one already exists + SetListeners(key StoreKey, listeners []WriteListener) +} +``` + +```go +type CacheWrap interface { + ... + + // CacheWrapWithListeners recursively wraps again with listening enabled + CacheWrapWithListeners(storeKey types.StoreKey, listeners []WriteListener) CacheWrap +} + +type CacheWrapper interface { + ... + + // CacheWrapWithListeners recursively wraps again with listening enabled + CacheWrapWithListeners(storeKey types.StoreKey, listeners []WriteListener) CacheWrap +} +``` + +### MultiStore implementation updates + +We will modify all of the `Store` and `MultiStore` implementations to satisfy these new interfaces, and adjust the `rootmulti` `GetKVStore` method +to wrap the returned `KVStore` with a `listenkv.Store` if listening is turned on for that `Store`. + +```go +func (rs *Store) GetKVStore(key types.StoreKey) types.KVStore { + store := rs.stores[key].(types.KVStore) + + if rs.TracingEnabled() { + store = tracekv.NewStore(store, rs.traceWriter, rs.traceContext) + } + if rs.ListeningEnabled(key) { + store = listenkv.NewStore(key, store, rs.listeners[key]) + } + + return store +} +``` + +We will also adjust the `cachemulti` constructor methods and the `rootmulti` `CacheMultiStore` method to forward the listeners +to and enable listening in the cache layer. + +```go +func (rs *Store) CacheMultiStore() types.CacheMultiStore { + stores := make(map[types.StoreKey]types.CacheWrapper) + for k, v := range rs.stores { + stores[k] = v + } + return cachemulti.NewStore(rs.db, stores, rs.keysByName, rs.traceWriter, rs.traceContext, rs.listeners) +} +``` + +### Exposing the data + +We will introduce a new `StreamingService` interface for exposing `WriteListener` data streams to external consumers. + +```go +// Hook interface used to hook into the ABCI message processing of the BaseApp +type Hook interface { + ListenBeginBlock(ctx sdk.Context, req abci.RequestBeginBlock, res abci.ResponseBeginBlock) // update the streaming service with the latest BeginBlock messages + ListenEndBlock(ctx sdk.Context, req abci.RequestEndBlock, res abci.ResponseEndBlock) // update the steaming service with the latest EndBlock messages + ListenDeliverTx(ctx sdk.Context, req abci.RequestDeliverTx, res abci.ResponseDeliverTx) // update the steaming service with the latest DeliverTx messages +} + +// StreamingService interface for registering WriteListeners with the BaseApp and updating the service with the ABCI messages using the hooks +type StreamingService interface { + Stream(wg *sync.WaitGroup, quitChan <-chan struct{}) // streaming service loop, awaits kv pairs and writes them to some destination stream or file + Listeners() map[sdk.StoreKey][]storeTypes.WriteListener // returns the streaming service's listeners for the BaseApp to register + Hook +} +``` + +#### Writing state changes to files + +We will introduce an implementation of `StreamingService` which writes state changes out to files as length-prefixed protobuf encoded `StoreKVPair`s. +This service uses the same `StoreKVPairWriteListener` for every KVStore, writing all the KV pairs from every KVStore +out to the same files, relying on the `StoreKey` field in the `StoreKVPair` protobuf message to later distinguish the source for each pair. + +The file naming schema is as such: +* After every `BeginBlock` request a new file is created with the name `block-{N}-begin`, where N is the block number. All +subsequent state changes are written out to this file until the first `DeliverTx` request is received. At the head of these files, + the length-prefixed protobuf encoded `BeginBlock` request is written, and the response is written at the tail. +* After every `DeliverTx` request a new file is created with the name `block-{N}-tx-{M}` where N is the block number and M +is the tx number in the block (i.e. 0, 1, 2...). All subsequent state changes are written out to this file until the next +`DeliverTx` request is received or an `EndBlock` request is received. At the head of these files, the length-prefixed protobuf + encoded `DeliverTx` request is written, and the response is written at the tail. +* After every `EndBlock` request a new file is created with the name `block-{N}-end`, where N is the block number. All +subsequent state changes are written out to this file until the next `BeginBlock` request is received. At the head of these files, + the length-prefixed protobuf encoded `EndBlock` request is written, and the response is written at the tail. + +```go +// FileStreamingService is a concrete implementation of StreamingService that writes state changes out to a file +type FileStreamingService struct { + listeners map[sdk.StoreKey][]storeTypes.WriteListener // the listeners that will be initialized with BaseApp + srcChan <-chan []byte // the channel that all of the WriteListeners write their data out to + filePrefix string // optional prefix for each of the generated files + writeDir string // directory to write files into + dstFile *os.File // the current write output file + marshaller codec.BinaryMarshaler // marshaller used for re-marshalling the ABCI messages to write them out to the destination files + stateCache [][]byte // cache the protobuf binary encoded StoreKVPairs in the order they are received +} +``` + +This streaming service uses a single instance of a simple intermediate `io.Writer` as the underlying `io.Writer` for its single `StoreKVPairWriteListener`, +It collects KV pairs from every KVStore synchronously off of the same channel, caching them in the order they are received, and then writing +them out to a file generated in response to an ABCI message hook. Files are named as outlined above, with optional prefixes to avoid potential naming collisions +across separate instances. + +```go +// intermediateWriter is used so that we do not need to update the underlying io.Writer inside the StoreKVPairWriteListener +// everytime we begin writing to a new file +type intermediateWriter struct { + outChan chan <-[]byte +} + +// NewIntermediateWriter create an instance of an intermediateWriter that sends to the provided channel +func NewIntermediateWriter(outChan chan <-[]byte) *intermediateWriter { + return &intermediateWriter{ + outChan: outChan, + } +} + +// Write satisfies io.Writer +func (iw *intermediateWriter) Write(b []byte) (int, error) { + iw.outChan <- b + return len(b), nil +} + +// NewFileStreamingService creates a new FileStreamingService for the provided writeDir, (optional) filePrefix, and storeKeys +func NewFileStreamingService(writeDir, filePrefix string, storeKeys []sdk.StoreKey, m codec.BinaryMarshaler) (*FileStreamingService, error) { + listenChan := make(chan []byte, 0) + iw := NewIntermediateWriter(listenChan) + listener := listen.NewStoreKVPairWriteListener(iw, m) + listners := make(map[sdk.StoreKey][]storeTypes.WriteListener, len(storeKeys)) + // in this case, we are using the same listener for each Store + for _, key := range storeKeys { + listeners[key] = listener + } + // check that the writeDir exists and is writeable so that we can catch the error here at initialization if it is not + // we don't open a dstFile until we receive our first ABCI message + if err := fileutil.IsDirWriteable(writeDir); err != nil { + return nil, err + } + return &FileStreamingService{ + listeners: listeners, + srcChan: listenChan, + filePrefix: filePrefix, + writeDir: writeDir, + marshaller: m, + stateCache: make([][]byte, 0), + }, nil +} + +// Listeners returns the StreamingService's underlying WriteListeners, use for registering them with the BaseApp +func (fss *FileStreamingService) Listeners() map[sdk.StoreKey][]storeTypes.WriteListener { + return fss.listeners +} + +func (fss *FileStreamingService) ListenBeginBlock(ctx sdk.Context, req abci.RequestBeginBlock, res abci.ResponseBeginBlock) { + // NOTE: this could either be done synchronously or asynchronously + // create a new file with the req info according to naming schema + // write req to file + // write all state changes cached for this stage to file + // reset cache + // write res to file + // close file +} + +func (fss *FileStreamingService) ListenEndBlock(ctx sdk.Context, req abci.RequestBeginBlock, res abci.ResponseBeginBlock) { + // NOTE: this could either be done synchronously or asynchronously + // create a new file with the req info according to naming schema + // write req to file + // write all state changes cached for this stage to file + // reset cache + // write res to file + // close file +} + +func (fss *FileStreamingService) ListenDeliverTx(ctx sdk.Context, req abci.RequestDeliverTx, res abci.ResponseDeliverTx) { + // NOTE: this could either be done synchronously or asynchronously + // create a new file with the req info according to naming schema + // NOTE: if the tx failed, handle accordingly + // write req to file + // write all state changes cached for this stage to file + // reset cache + // write res to file + // close file +} + +// Stream spins up a goroutine select loop which awaits length-prefixed binary encoded KV pairs and caches them in the order they were received +func (fss *FileStreamingService) Stream(wg *sync.WaitGroup, quitChan <-chan struct{}) { + wg.Add(1) + go func() { + defer wg.Done() + for { + select { + case <-quitChan: + return + case by := <-fss.srcChan: + append(fss.stateCache, by) + } + } + }() +} +``` + +Writing to a file is the simplest approach for streaming the data out to consumers. +This approach also provides the advantages of being persistent and durable, and the files can be read directly, +or an auxiliary streaming services can read from the files and serve the data over a remote interface. + +#### Auxiliary streaming service + +We will create a separate standalone process that reads and internally queues the state as it is written out to these files +and serves the data over a gRPC API. This API will allow filtering of requested data, e.g. by block number, block/tx hash, ABCI message type, +whether a DeliverTx message failed or succeeded, etc. In addition to unary RPC endpoints this service will expose `stream` RPC endpoints for realtime subscriptions. + +#### File pruning + +Without pruning the number of files can grow indefinitely, this may need to be managed by +the developer in an application or even module-specific manner (e.g. log rotation). +The file naming schema facilitates pruning by block number and/or ABCI message. +The gRPC auxiliary streaming service introduced above will include an option to remove the files as it consumes their data. + +### Configuration + +We will provide detailed documentation on how to configure a `FileStreamingService` from within an app's `AppCreator`, +using the provided `AppOptions` and TOML configuration fields. + +#### BaseApp registration + +We will add a new method to the `BaseApp` to enable the registration of `StreamingService`s: + +```go +// RegisterStreamingService is used to register a streaming service with the BaseApp +func (app *BaseApp) RegisterHooks(s StreamingService) { + // set the listeners for each StoreKey + for key, lis := range s.Listeners() { + app.cms.SetListeners(key, lis) + } + // register the streaming service hooks within the BaseApp + // BaseApp will pass BeginBlock, DeliverTx, and EndBlock requests and responses to the streaming services to update their ABCI context using these hooks + app.hooks = append(app.hooks, s) +} +``` + +We will also modify the `BeginBlock`, `EndBlock`, and `DeliverTx` methods to pass ABCI requests and responses to any streaming service hooks registered +with the `BaseApp`. + + +```go +func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { + + ... + + // Call the streaming service hooks with the BeginBlock messages + for _ hook := range app.hooks { + hook.ListenBeginBlock(app.deliverState.ctx, req, res) + } + + return res +} +``` + +```go +func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) { + + ... + + // Call the streaming service hooks with the EndBlock messages + for _, hook := range app.hooks { + hook.ListenEndBlock(app.deliverState.ctx, req, res) + } + + return res +} +``` + +```go +func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx { + + ... + + gInfo, result, err := app.runTx(runTxModeDeliver, req.Tx) + if err != nil { + resultStr = "failed" + res := sdkerrors.ResponseDeliverTx(err, gInfo.GasWanted, gInfo.GasUsed, app.trace) + // If we throw and error, be sure to still call the streaming service's hook + for _, hook := range app.hooks { + hook.ListenDeliverTx(app.deliverState.ctx, req, res) + } + return res + } + + res := abci.ResponseDeliverTx{ + GasWanted: int64(gInfo.GasWanted), // TODO: Should type accept unsigned ints? + GasUsed: int64(gInfo.GasUsed), // TODO: Should type accept unsigned ints? + Log: result.Log, + Data: result.Data, + Events: sdk.MarkEventsToIndex(result.Events, app.indexEvents), + } + + // Call the streaming service hooks with the DeliverTx messages + for _, hook := range app.hook { + hook.ListenDeliverTx(app.deliverState.ctx, req, res) + } + + return res +} +``` + +#### TOML Configuration + +We will provide standard TOML configuration options for configuring a `FileStreamingService` for specific `Store`s. +Note: the actual namespace is TBD. + +```toml +[store] + streamers = [ # if len(streamers) > 0 we are streaming + "file", + ] + +[streamers] + [streamers.file] + keys = ["list", "of", "store", "keys", "we", "want", "to", "expose", "for", "this", "streaming", "service"] + writeDir = "path to the write directory" + prefix = "optional prefix to prepend to the generated file names" +``` + +We will also provide a mapping of the TOML `store.streamers` "file" configuration option to a helper functions for constructing the specified +streaming service. In the future, as other streaming services are added, their constructors will be added here as well. + +```go +// StreamingServiceConstructor is used to construct a streaming service +type StreamingServiceConstructor func(opts servertypes.AppOptions, keys []sdk.StoreKey) (StreamingService, error) + +// StreamingServiceType enum for specifying the type of StreamingService +type StreamingServiceType int + +const ( + Unknown StreamingServiceType = iota + File + // add more in the future +) + +// NewStreamingServiceType returns the StreamingServiceType corresponding to the provided name +func NewStreamingServiceType(name string) StreamingServiceType { + switch strings.ToLower(name) { + case "file", "f": + return File + default: + return Unknown + } +} + +// String returns the string name of a StreamingServiceType +func (sst StreamingServiceType) String() string { + switch sst { + case File: + return "file" + default: + return "" + } +} + +// StreamingServiceConstructorLookupTable is a mapping of StreamingServiceTypes to StreamingServiceConstructors +var StreamingServiceConstructorLookupTable = map[StreamingServiceType]StreamingServiceConstructor{ + File: FileStreamingConstructor, +} + +// NewStreamingServiceConstructor returns the StreamingServiceConstructor corresponding to the provided name +func NewStreamingServiceConstructor(name string) (StreamingServiceConstructor, error) { + ssType := NewStreamingServiceType(name) + if ssType == Unknown { + return nil, fmt.Errorf("unrecognized streaming service name %s", name) + } + if constructor, ok := StreamingServiceConstructorLookupTable[ssType]; ok { + return constructor, nil + } + return nil, fmt.Errorf("streaming service constructor of type %s not found", ssType.String()) +} + +// FileStreamingConstructor is the StreamingServiceConstructor function for creating a FileStreamingService +func FileStreamingConstructor(opts servertypes.AppOptions, keys []sdk.StoreKey) (StreamingService, error) { + filePrefix := cast.ToString(opts.Get("streamers.file.prefix")) + fileDir := cast.ToString(opts.Get("streamers.file.writeDir")) + return streaming.NewFileStreamingService(fileDir, filePrefix, keys), nil +} +``` + +#### Example configuration + +As a demonstration, we will implement the state watching features as part of SimApp. +For example, the below is a very rudimentary integration of the state listening features into the SimApp `AppCreator` function: + + +```go +func NewSimApp( + logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, skipUpgradeHeights map[int64]bool, + homePath string, invCheckPeriod uint, encodingConfig simappparams.EncodingConfig, + appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp), +) *SimApp { + + ... + + keys := sdk.NewKVStoreKeys( + authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, + minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, + govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, + evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, + ) + + // configure state listening capabilities using AppOptions + listeners := cast.ToStringSlice(appOpts.Get("store.streamers")) + for _, listenerName := range listeners { + // get the store keys allowed to be exposed for this streaming service/state listeners + exposeKeyStrs := cast.ToStringSlice(appOpts.Get(fmt.Sprintf("streamers.%s.keys", listenerName)) + exposeStoreKeys = make([]storeTypes.StoreKey, 0, len(exposeKeyStrs)) + for _, keyStr := range exposeKeyStrs { + if storeKey, ok := keys[keyStr]; ok { + exposeStoreKeys = append(exposeStoreKeys, storeKey) + } + } + // get the constructor for this listener name + constructor, err := baseapp.NewStreamingServiceConstructor(listenerName) + if err != nil { + tmos.Exit(err.Error()) // or continue? + } + // generate the streaming service using the constructor, appOptions, and the StoreKeys we want to expose + streamingService, err := constructor(appOpts, exposeStoreKeys) + if err != nil { + tmos.Exit(err.Error()) + } + // register the streaming service with the BaseApp + bApp.RegisterStreamingService(streamingService) + // waitgroup and quit channel for optional shutdown coordination of the streaming service + wg := new(sync.WaitGroup) + quitChan := new(chan struct{})) + // kick off the background streaming service loop + streamingService.Stream(wg, quitChan) // maybe this should be done from inside BaseApp instead? + } + + ... + + return app +} +``` + +## Consequences + +These changes will provide a means of subscribing to KVStore state changes in real time. + +### Backwards Compatibility + +- This ADR changes the `MultiStore`, `CacheWrap`, and `CacheWrapper` interfaces, implementations supporting the previous version of these interfaces will not support the new ones + +### Positive + +- Ability to listen to KVStore state changes in real time and expose these events to external consumers + +### Negative + +- Changes `MultiStore`, `CacheWrap`, and `CacheWrapper` interfaces + +### Neutral + +- Introduces additional- but optional- complexity to configuring and running a cosmos application +- If an application developer opts to use these features to expose data, they need to be aware of the ramifications/risks of that data exposure as it pertains to the specifics of their application From c0c0665d4e9c76f6fc613a5496bbc6c1b4c47c33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Feb 2021 13:45:56 +0000 Subject: [PATCH 105/152] build(deps): bump actions/cache from v2.1.3 to v2.1.4 (#8521) Bumps [actions/cache](https://github.com/actions/cache) from v2.1.3 to v2.1.4. - [Release notes](https://github.com/actions/cache/releases) - [Commits](https://github.com/actions/cache/compare/v2.1.3...26968a09c0ea4f3e233fdddbafd1166051a095f6) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-sims.yml | 4 ++-- .github/workflows/sims.yml | 10 +++++----- .github/workflows/test.yml | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release-sims.yml b/.github/workflows/release-sims.yml index 68ca31051135..82e68ff41b07 100644 --- a/.github/workflows/release-sims.yml +++ b/.github/workflows/release-sims.yml @@ -30,7 +30,7 @@ jobs: - name: install runsim run: | export GO111MODULE="on" && go get github.com/cosmos/tools/cmd/runsim@v1.0.0 - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-runsim-binary @@ -40,7 +40,7 @@ jobs: needs: [build, install-runsim] steps: - uses: actions/checkout@v2 - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-runsim-binary diff --git a/.github/workflows/sims.yml b/.github/workflows/sims.yml index d50ddb63a289..a84570b80745 100644 --- a/.github/workflows/sims.yml +++ b/.github/workflows/sims.yml @@ -39,7 +39,7 @@ jobs: run: go version - name: Install runsim run: export GO111MODULE="on" && go get github.com/cosmos/tools/cmd/runsim@v1.0.0 - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-runsim-binary @@ -60,7 +60,7 @@ jobs: **/**.go go.mod go.sum - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-runsim-binary @@ -88,7 +88,7 @@ jobs: go.sum SET_ENV_NAME_INSERTIONS: 1 SET_ENV_NAME_LINES: 1 - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-runsim-binary @@ -116,7 +116,7 @@ jobs: go.sum SET_ENV_NAME_INSERTIONS: 1 SET_ENV_NAME_LINES: 1 - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-runsim-binary @@ -144,7 +144,7 @@ jobs: go.sum SET_ENV_NAME_INSERTIONS: 1 SET_ENV_NAME_LINES: 1 - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-runsim-binary diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dd09041862d3..b499f2822817 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,7 +26,7 @@ jobs: - name: install tparse run: | export GO111MODULE="on" && go get github.com/mfridman/tparse@v0.8.3 - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-tparse-binary @@ -254,7 +254,7 @@ jobs: with: name: "${{ github.sha }}-03-race-output" if: env.GIT_DIFF - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-tparse-binary From b55913ddad8730c4dc69dd03e03596c8b49f68ed Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Sat, 6 Feb 2021 00:57:12 +1000 Subject: [PATCH 106/152] fix comments and add CHANGELOG --- CHANGELOG.md | 1 + docs/architecture/adr-037-gov-split-vote.md | 2 +- x/gov/client/utils/utils_test.go | 56 +++++++++++++++++++++ x/gov/keeper/tally_test.go | 1 + x/gov/types/msgs.go | 4 ++ x/gov/types/vote.go | 13 +++-- 6 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 x/gov/client/utils/utils_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index cab64e9c935e..93f994e4f632 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (x/gov) [\#7733](https://github.com/cosmos/cosmos-sdk/pull/7733) ADR 037 Implementation: Governance Split Votes * (x/bank) [\#8302](https://github.com/cosmos/cosmos-sdk/issues/8302) Add gRPC and CLI queries for client denomination metadata. * (tendermint) [\#8316](https://github.com/cosmos/cosmos-sdk/pull/8316) Bump Tendermint version to [v0.34.2](https://github.com/tendermint/tendermint/releases/tag/v0.34.2) diff --git a/docs/architecture/adr-037-gov-split-vote.md b/docs/architecture/adr-037-gov-split-vote.md index ccc93e8bf245..3dfa59cca912 100644 --- a/docs/architecture/adr-037-gov-split-vote.md +++ b/docs/architecture/adr-037-gov-split-vote.md @@ -6,7 +6,7 @@ ## Status -Proposed +Accepted ## Abstract diff --git a/x/gov/client/utils/utils_test.go b/x/gov/client/utils/utils_test.go new file mode 100644 index 000000000000..0da66b3c29ba --- /dev/null +++ b/x/gov/client/utils/utils_test.go @@ -0,0 +1,56 @@ +package utils + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestNormalizeWeightedVoteOptions(t *testing.T) { + cases := map[string]struct { + options string + normalized string + }{ + "simple Yes": { + options: "Yes", + normalized: "VOTE_OPTION_YES=1", + }, + "simple yes": { + options: "yes", + normalized: "VOTE_OPTION_YES=1", + }, + "formal yes": { + options: "yes=1", + normalized: "VOTE_OPTION_YES=1", + }, + "half yes half no": { + options: "yes=0.5,no=0.5", + normalized: "VOTE_OPTION_YES=0.5,VOTE_OPTION_NO=0.5", + }, + "3 options": { + options: "Yes=0.5,No=0.4,NoWithVeto=0.1", + normalized: "VOTE_OPTION_YES=0.5,VOTE_OPTION_NO=0.4,VOTE_OPTION_NO_WITH_VETO=0.1", + }, + "zero weight option": { + options: "Yes=0.5,No=0.5,NoWithVeto=0", + normalized: "VOTE_OPTION_YES=0.5,VOTE_OPTION_NO=0.5,VOTE_OPTION_NO_WITH_VETO=0", + }, + "minus weight option": { + options: "Yes=0.5,No=0.6,NoWithVeto=-0.1", + normalized: "VOTE_OPTION_YES=0.5,VOTE_OPTION_NO=0.6,VOTE_OPTION_NO_WITH_VETO=-0.1", + }, + "empty options": { + options: "", + normalized: "=1", + }, + "not available option": { + options: "Yessss=1", + normalized: "Yessss=1", + }, + } + + for _, tc := range cases { + normalized := NormalizeWeightedVoteOptions(tc.options) + require.Equal(t, normalized, tc.normalized) + } +} diff --git a/x/gov/keeper/tally_test.go b/x/gov/keeper/tally_test.go index 89e4a7c2bfbf..ef9cbd02789a 100644 --- a/x/gov/keeper/tally_test.go +++ b/x/gov/keeper/tally_test.go @@ -423,6 +423,7 @@ func TestTallyJailedValidator(t *testing.T) { require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[0], types.NewNonSplitVoteOption(types.OptionYes))) require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[1], types.NewNonSplitVoteOption(types.OptionNo))) + require.NoError(t, app.GovKeeper.AddVote(ctx, proposalID, addrs[2], types.NewNonSplitVoteOption(types.OptionNo))) proposal, ok := app.GovKeeper.GetProposal(ctx, proposalID) require.True(t, ok) diff --git a/x/gov/types/msgs.go b/x/gov/types/msgs.go index 157c088d5846..f1c351e6ddca 100644 --- a/x/gov/types/msgs.go +++ b/x/gov/types/msgs.go @@ -258,6 +258,10 @@ func (msg MsgVoteWeighted) ValidateBasic() error { return sdkerrors.Wrap(ErrInvalidVote, "Total weight overflow 1.00") } + if totalWeight.LT(sdk.NewDec(1)) { + return sdkerrors.Wrap(ErrInvalidVote, "Total weight lower than 1.00") + } + return nil } diff --git a/x/gov/types/vote.go b/x/gov/types/vote.go index dc88be0ec7d2..baa61920a1f8 100644 --- a/x/gov/types/vote.go +++ b/x/gov/types/vote.go @@ -1,13 +1,13 @@ package types import ( - "encoding/json" "fmt" "strings" yaml "gopkg.in/yaml.v2" sdk "github.com/cosmos/cosmos-sdk/types" + proto "github.com/gogo/protobuf/proto" ) // NewVote creates a new Vote instance @@ -62,16 +62,19 @@ func NewNonSplitVoteOption(option VoteOption) WeightedVoteOptions { } func (v WeightedVoteOption) String() string { - out, _ := json.Marshal(v) + out, _ := proto.Marshal(&v) return string(out) } // WeightedVoteOptions describes array of WeightedVoteOptions type WeightedVoteOptions []WeightedVoteOption -func (v WeightedVoteOptions) String() string { - out, _ := json.Marshal(v) - return string(out) +func (v WeightedVoteOptions) String() (out string) { + for _, opt := range v { + out += opt.String() + "\n" + } + + return strings.TrimSpace(out) } // ValidWeightedVoteOption returns true if the sub vote is valid and false otherwise. From c54b3c43448c46438de704f35d16c1cfeabc281e Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 5 Feb 2021 15:17:52 +0000 Subject: [PATCH 107/152] cosmovisor: ln -s docs/run-node/cosmovisor.md cosmovisor/README.md (#8526) Avoid duplication of contents. --- cosmovisor/README.md | 149 +------------------------------------------ 1 file changed, 1 insertion(+), 148 deletions(-) mode change 100644 => 120000 cosmovisor/README.md diff --git a/cosmovisor/README.md b/cosmovisor/README.md deleted file mode 100644 index 3892efd0db2d..000000000000 --- a/cosmovisor/README.md +++ /dev/null @@ -1,148 +0,0 @@ -# Cosmovisor - -This is a tiny shim around Cosmos SDK binaries that use the upgrade -module that allows for smooth and configurable management of upgrading -binaries as a live chain is upgraded, and can be used to simplify validator -devops while doing upgrades or to make syncing a full node for genesis -simple. The `cosmovisor` will monitor the stdout of the daemon to look -for messages from the upgrade module indicating a pending or required upgrade -and act appropriately. (With better integrations possible in the future). - -## Arguments - -`cosmovisor` is a shim around a native binary. All arguments passed to the `cosmovisor` -command will be passed to the current daemon binary (as a subprocess). - It will return stdout and stderr of the subprocess as -it's own. Because of that, it cannot accept any command line arguments, nor -print anything to output (unless it dies before executing a binary). - -Configuration will be passed in the following environmental variables: - -* `DAEMON_HOME` is the location where upgrade binaries should be kept (can -be `$HOME/.gaiad` or `$HOME/.xrnd`) -* `DAEMON_NAME` is the name of the binary itself (eg. `xrnd`, `gaiad`, `simd`) -* `DAEMON_ALLOW_DOWNLOAD_BINARIES` (optional) if set to `true` will enable auto-downloading of new binaries -(for security reasons, this is intended for fullnodes rather than validators) -* `DAEMON_RESTART_AFTER_UPGRADE` (optional) if set to `true` it will restart the sub-process with the same args -(but new binary) after a successful upgrade. By default, the `cosmovisor` dies afterward and allows the cosmovisor -to restart it if needed. Note that this will not auto-restart the child if there was an error. - -## Folder Layout - -`$DAEMON_HOME/cosmovisor` is expected to belong completely to the cosmovisor and -subprocesses -controlled by it. Under this folder, we will see the following: - -``` -. -├── current -> genesis or upgrades/ -├── genesis -│   └── bin -│   └── $DAEMON_NAME -└── upgrades - └── - └── bin - └── $DAEMON_NAME -``` - -Each version of the chain is stored under either `genesis` or `upgrades/`, which holds `bin/$DAEMON_NAME` -along with any other needed files (maybe the cli client? maybe some dlls?). `current` is a symlink to the currently -active folder (so `current/bin/$DAEMON_NAME` is the binary) - -Note: the `` after `upgrades` is the URI-encoded name of the upgrade as specified in the upgrade module plan. - -Please note that `$DAEMON_HOME/cosmovisor` just stores the *binaries* and associated *program code*. -The `cosmovisor` binary can be stored in any typical location (eg `/usr/local/bin`). The actual blockchain -program will store it's data under `$GAIA_HOME` etc, which is independent of the `$DAEMON_HOME`. You can -choose to export `GAIA_HOME=$DAEMON_HOME` and then end up with a configuation like the following, but this -is left as a choice to the admin for best directory layout. - -``` -.gaiad -├── config -├── data -└── cosmovisor -``` - -## Usage - -Basic Usage: - -* The admin is responsible for installing the `cosmovisor` and setting it as a eg. systemd service to auto-restart, along with proper environmental variables -* The admin is responsible for installing the `genesis` folder manually -* The `cosmovisor` will set the `current` link to point to `genesis` at first start (when no `current` link exists) -* The admin is (generally) responsible for installing the `upgrades/` folders manually -* The `cosmovisor` handles switching over the binaries at the correct points, so the admin can prepare days in advance and relax at upgrade time - -Note that chains that wish to support upgrades may package up a genesis `cosmovisor` tar file with this info, just as they -prepare the genesis binary tar file. In fact, they may offer a tar file will all upgrades up to current point for easy download -for those who wish to sync a fullnode from start. - -The `DAEMON` specific code, like the tendermint config, the application db, syncing blocks, etc is done as normal. -The same eg. `GAIA_HOME` directives and command-line flags work, just the binary name is different. - -## Upgradeable Binary Specification - -In the basic version, the `cosmovisor` will read the stdout log messages -to determine when an upgrade is needed. We are considering more complex solutions -via signaling of some sort, but starting with the simple design: - -* when an upgrade is needed the binary will print a line that matches this -regular expression: `UPGRADE "(.*)" NEEDED at height (\d+):(.*)`. -* the second match in the above regular expression can be a JSON object with -a `binaries` key as described above - -The name (first regexp) will be used to select the new binary to run. If it is present, -the current subprocess will be killed, `current` will be upgraded to the new directory, -and the new binary will be launched. - -**Question** should we just kill the `cosmovisor` after it does the updates? -so it gets a clean restart and just runs the new binary (under `current`). -it should be safe to restart (as a service). - -## Auto-Download - -Generally, the system requires that the administrator place all relevant binaries -on the disk before the upgrade happens. However, for people who don't need such -control and want an easier setup (maybe they are syncing a non-validating fullnode -and want to do little maintenance), there is another option. - -If you set `DAEMON_ALLOW_DOWNLOAD_BINARIES=on` then when an upgrade is triggered and no local binary -can be found, the `cosmovisor` will attempt to download and install the binary itself. -The plan stored in the upgrade module has an info field for arbitrary json. -This info is expected to be outputed on the halt log message. There are two -valid format to specify a download in such a message: - -1. Store an os/architecture -> binary URI map in the upgrade plan info field -as JSON under the `"binaries"` key, eg: -```json -{ - "binaries": { - "linux/amd64":"https://example.com/gaia.zip?checksum=sha256:aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f" - } -} -``` -The `"any"` key, if it exists, will be used as a default if there is not a specific os/architecture key. -2. Store a link to a file that contains all information in the above format (eg. if you want -to specify lots of binaries, changelog info, etc without filling up the blockchain). - -e.g `https://example.com/testnet-1001-info.json?checksum=sha256:deaaa99fda9407c4dbe1d04bd49bab0cc3c1dd76fa392cd55a9425be074af01e` - -This file contained in link will be retrieved by [go-getter](https://github.com/hashicorp/go-getter) -and the "binaries" field will be parsed as above. - -If there is no local binary, `DAEMON_ALLOW_DOWNLOAD_BINARIES=true`, and we can access a canonical url for the new binary, -then the `cosmovisor` will download it with [go-getter](https://github.com/hashicorp/go-getter) and -unpack it into the `upgrades/` folder to be run as if we installed it manually - -Note that for this mechanism to provide strong security guarantees, all URLs should include a -sha{256,512} checksum. This ensures that no false binary is run, even if someone hacks the server -or hijacks the dns. go-getter will always ensure the downloaded file matches the checksum if it -is provided. And also handles unpacking archives into directories (so these download links should be -a zip of all data in the bin directory). - -To properly create a checksum on linux, you can use the `sha256sum` utility. eg. -`sha256sum ./testdata/repo/zip_directory/autod.zip` -which should return `29139e1381b8177aec909fab9a75d11381cab5adf7d3af0c05ff1c9c117743a7`. -You can also use `sha512sum` if you like longer hashes, or `md5sum` if you like to use broken hashes. -Make sure to set the hash algorithm properly in the checksum argument to the url. diff --git a/cosmovisor/README.md b/cosmovisor/README.md new file mode 120000 index 000000000000..a37c5c784512 --- /dev/null +++ b/cosmovisor/README.md @@ -0,0 +1 @@ +../docs/run-node/cosmovisor.md \ No newline at end of file From 46d6fa0ecc9e52e2fac3a812c1c7808e5408f26f Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Sat, 6 Feb 2021 01:21:22 +1000 Subject: [PATCH 108/152] fix simulation test, marshal json process --- x/gov/simulation/operations.go | 2 +- x/gov/types/vote.go | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/x/gov/simulation/operations.go b/x/gov/simulation/operations.go index 3b87e8accd5c..8ce709da834f 100644 --- a/x/gov/simulation/operations.go +++ b/x/gov/simulation/operations.go @@ -386,7 +386,7 @@ func operationSimulateMsgVoteWeighted(ak types.AccountKeeper, bk types.BankKeepe return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } diff --git a/x/gov/types/vote.go b/x/gov/types/vote.go index baa61920a1f8..72fa0bfbf338 100644 --- a/x/gov/types/vote.go +++ b/x/gov/types/vote.go @@ -1,13 +1,12 @@ package types import ( + "encoding/json" "fmt" "strings" - yaml "gopkg.in/yaml.v2" - sdk "github.com/cosmos/cosmos-sdk/types" - proto "github.com/gogo/protobuf/proto" + yaml "gopkg.in/yaml.v2" ) // NewVote creates a new Vote instance @@ -62,7 +61,7 @@ func NewNonSplitVoteOption(option VoteOption) WeightedVoteOptions { } func (v WeightedVoteOption) String() string { - out, _ := proto.Marshal(&v) + out, _ := json.Marshal(v) return string(out) } From c5c049a0452b347d5e0e7ec0416b28f04f035a83 Mon Sep 17 00:00:00 2001 From: SaReN Date: Fri, 5 Feb 2021 21:05:03 +0530 Subject: [PATCH 109/152] Persist evidence in equivocation handler (#8502) * Persist evidence in handler * update docs * update docs Co-authored-by: Alessio Treglia Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- CHANGELOG.md | 1 + x/evidence/keeper/infraction.go | 1 + x/evidence/keeper/infraction_test.go | 4 ++++ x/evidence/spec/01_concepts.md | 3 ++- 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12a2d94b31dc..e745b57961ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/{bank,distrib,gov,slashing,staking}) [\#8363](https://github.com/cosmos/cosmos-sdk/issues/8363) Store keys have been modified to allow for variable-length addresses. * (x/ibc) [\#8266](https://github.com/cosmos/cosmos-sdk/issues/8266) Add amino JSON for IBC messages in order to support Ledger text signing. +* (x/evidence) [\#8502](https://github.com/cosmos/cosmos-sdk/pull/8502) `HandleEquivocationEvidence` persists the evidence to state. ### Improvements diff --git a/x/evidence/keeper/infraction.go b/x/evidence/keeper/infraction.go index 427c8de429ed..3ae74bc216de 100644 --- a/x/evidence/keeper/infraction.go +++ b/x/evidence/keeper/infraction.go @@ -119,4 +119,5 @@ func (k Keeper) HandleEquivocationEvidence(ctx sdk.Context, evidence *types.Equi k.slashingKeeper.JailUntil(ctx, consAddr, types.DoubleSignJailEndTime) k.slashingKeeper.Tombstone(ctx, consAddr) + k.SetEvidence(ctx, evidence) } diff --git a/x/evidence/keeper/infraction_test.go b/x/evidence/keeper/infraction_test.go index 0f1adee14f46..4c7368b1df7c 100644 --- a/x/evidence/keeper/infraction_test.go +++ b/x/evidence/keeper/infraction_test.go @@ -69,6 +69,10 @@ func (suite *KeeperTestSuite) TestHandleDoubleSign() { tstaking.Ctx = ctx tstaking.Denom = stakingParams.BondDenom tstaking.Undelegate(sdk.AccAddress(operatorAddr), operatorAddr, totalBond, true) + + // query evidence from store + evidences := suite.app.EvidenceKeeper.GetAllEvidence(ctx) + suite.Len(evidences, 1) } func (suite *KeeperTestSuite) TestHandleDoubleSign_TooOld() { diff --git a/x/evidence/spec/01_concepts.md b/x/evidence/spec/01_concepts.md index 78a16523daaf..0d9f1a025d80 100644 --- a/x/evidence/spec/01_concepts.md +++ b/x/evidence/spec/01_concepts.md @@ -66,7 +66,8 @@ The `Handler` (defined below) is responsible for executing the entirety of the business logic for handling `Evidence`. This typically includes validating the evidence, both stateless checks via `ValidateBasic` and stateful checks via any keepers provided to the `Handler`. In addition, the `Handler` may also perform -capabilities such as slashing and jailing a validator. +capabilities such as slashing and jailing a validator. All `Evidence` handled +by the `Handler` should be persisted. ```go // Handler defines an agnostic Evidence handler. The handler is responsible From 8001e3ca3a5f15ab85e2a50e2eca754803f5fd8c Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Sat, 6 Feb 2021 21:51:26 +0000 Subject: [PATCH 110/152] bank: don't ignore errors returned by Balance.GetAddress() (#8531) Closes: #8530 --- x/bank/types/balance.go | 6 +++++- x/bank/types/balance_test.go | 41 ++++++++++++++++++++++++++++-------- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/x/bank/types/balance.go b/x/bank/types/balance.go index 93517a1d925b..49330bc06af1 100644 --- a/x/bank/types/balance.go +++ b/x/bank/types/balance.go @@ -15,7 +15,11 @@ var _ exported.GenesisBalance = (*Balance)(nil) // GetAddress returns the account address of the Balance object. func (b Balance) GetAddress() sdk.AccAddress { - addr, _ := sdk.AccAddressFromBech32(b.Address) + addr, err := sdk.AccAddressFromBech32(b.Address) + if err != nil { + panic(fmt.Errorf("couldn't convert %q to account address: %v", b.Address, err)) + } + return addr } diff --git a/x/bank/types/balance_test.go b/x/bank/types/balance_test.go index 73e4d8eff387..6282b2478b19 100644 --- a/x/bank/types/balance_test.go +++ b/x/bank/types/balance_test.go @@ -1,4 +1,4 @@ -package types +package types_test import ( "testing" @@ -6,34 +6,34 @@ import ( "github.com/stretchr/testify/require" sdk "github.com/cosmos/cosmos-sdk/types" + bank "github.com/cosmos/cosmos-sdk/x/bank/types" ) func TestBalanceValidate(t *testing.T) { - testCases := []struct { name string - balance Balance + balance bank.Balance expErr bool }{ { "valid balance", - Balance{ + bank.Balance{ Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", Coins: sdk.Coins{sdk.NewInt64Coin("uatom", 1)}, }, false, }, - {"empty balance", Balance{}, true}, + {"empty balance", bank.Balance{}, true}, { "nil balance coins", - Balance{ + bank.Balance{ Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", }, true, }, { "dup coins", - Balance{ + bank.Balance{ Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", Coins: sdk.Coins{ sdk.NewInt64Coin("uatom", 1), @@ -44,7 +44,7 @@ func TestBalanceValidate(t *testing.T) { }, { "invalid coin denom", - Balance{ + bank.Balance{ Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", Coins: sdk.Coins{ sdk.Coin{Denom: "", Amount: sdk.OneInt()}, @@ -54,7 +54,7 @@ func TestBalanceValidate(t *testing.T) { }, { "negative coin", - Balance{ + bank.Balance{ Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", Coins: sdk.Coins{ sdk.Coin{Denom: "uatom", Amount: sdk.NewInt(-1)}, @@ -78,3 +78,26 @@ func TestBalanceValidate(t *testing.T) { }) } } + +func TestBalance_GetAddress(t *testing.T) { + tests := []struct { + name string + Address string + wantPanic bool + }{ + {"empty address", "", true}, + {"malformed address", "invalid", true}, + {"valid address", "cosmos1vy0ga0klndqy92ceqehfkvgmn4t94eteq4hmqv", false}, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + b := bank.Balance{Address: tt.Address} + if tt.wantPanic { + require.Panics(t, func() { b.GetAddress() }) + } else { + require.False(t, b.GetAddress().Empty()) + } + }) + } +} From bb85a690abc78abec1588709ee884c4d33d799e3 Mon Sep 17 00:00:00 2001 From: Afanti Date: Mon, 8 Feb 2021 17:55:24 +0800 Subject: [PATCH 111/152] Fix typo in context and node docs (#8533) * Update context.md * fix typo in the node document --- docs/core/context.md | 2 +- docs/core/node.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/core/context.md b/docs/core/context.md index c9e89b16a471..ee022d900ee0 100644 --- a/docs/core/context.md +++ b/docs/core/context.md @@ -13,7 +13,7 @@ The `context` is a data structure intended to be passed from function to functio ## Context Definition -The SDK `Context` is a custom data structure that contains Go's stdlib [`context`](https://golang.org/pkg/context) as its base, and has many additional types within its definition that are specific to the Cosmos SDK. he `Context` is integral to transaction processing in that it allows modules to easily access their respective [store](./store.md#base-layer-kvstores) in the [`multistore`](./store.md#multistore) and retrieve transactional context such as the block header and gas meter. +The SDK `Context` is a custom data structure that contains Go's stdlib [`context`](https://golang.org/pkg/context) as its base, and has many additional types within its definition that are specific to the Cosmos SDK. The `Context` is integral to transaction processing in that it allows modules to easily access their respective [store](./store.md#base-layer-kvstores) in the [`multistore`](./store.md#multistore) and retrieve transactional context such as the block header and gas meter. +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/context.go#L16-L39 diff --git a/docs/core/node.md b/docs/core/node.md index 005aab3ab188..661322b2c010 100644 --- a/docs/core/node.md +++ b/docs/core/node.md @@ -16,7 +16,7 @@ The full-node client of any SDK application is built by running a `main` functio In general, developers will implement the `main.go` function with the following structure: -- First, an [`appCodec`](./encoding.md) is instanciated for the application. +- First, an [`appCodec`](./encoding.md) is instantiated for the application. - Then, the `config` is retrieved and config parameters are set. This mainly involves setting the bech32 prefixes for [addresses and pubkeys](../basics/accounts.md#addresses-and-pubkeys). +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/config.go#L13-L24 - Using [cobra](https://github.com/spf13/cobra), the root command of the full-node client is created. After that, all the custom commands of the application are added using the `AddCommand()` method of `rootCmd`. From 816306b85addae6350bd380997f2f4bf9dce9471 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Feb 2021 13:00:11 +0000 Subject: [PATCH 112/152] build(deps): bump github.com/improbable-eng/grpc-web (#8536) Bumps [github.com/improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web) from 0.13.0 to 0.14.0. - [Release notes](https://github.com/improbable-eng/grpc-web/releases) - [Changelog](https://github.com/improbable-eng/grpc-web/blob/master/CHANGELOG.md) - [Commits](https://github.com/improbable-eng/grpc-web/compare/v0.13.0...v0.14.0) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- go.mod | 3 ++- go.sum | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1b56715dee82..37fa821ac6bf 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/hashicorp/golang-lru v0.5.4 - github.com/improbable-eng/grpc-web v0.13.0 + github.com/improbable-eng/grpc-web v0.14.0 github.com/magiconair/properties v1.8.4 github.com/mattn/go-isatty v0.0.12 github.com/otiai10/copy v1.4.2 @@ -55,6 +55,7 @@ require ( google.golang.org/protobuf v1.25.0 gopkg.in/ini.v1 v1.61.0 // indirect gopkg.in/yaml.v2 v2.4.0 + nhooyr.io/websocket v1.8.6 // indirect ) replace google.golang.org/grpc => google.golang.org/grpc v1.33.2 diff --git a/go.sum b/go.sum index b36fb8fad57b..266ad810f42a 100644 --- a/go.sum +++ b/go.sum @@ -201,6 +201,10 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -212,10 +216,24 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/gogo/gateway v1.1.0 h1:u0SuhL9+Il+UbjM9VIE3ntfRujKbvVpFvNB4HbjeVQ0= @@ -285,6 +303,7 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7 github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= @@ -343,8 +362,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/improbable-eng/grpc-web v0.13.0 h1:7XqtaBWaOCH0cVGKHyvhtcuo6fgW32Y10yRKrDHFHOc= -github.com/improbable-eng/grpc-web v0.13.0/go.mod h1:6hRR09jOEG81ADP5wCQju1z71g6OL4eEvELdran/3cs= +github.com/improbable-eng/grpc-web v0.14.0 h1:GdoK+cXABdB+1keuqsV1drSFO2XLYIxqt/4Rj8SWGBk= +github.com/improbable-eng/grpc-web v0.14.0/go.mod h1:6hRR09jOEG81ADP5wCQju1z71g6OL4eEvELdran/3cs= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= @@ -363,6 +382,7 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= @@ -377,6 +397,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= +github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eTO0Q8= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -388,6 +410,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= @@ -433,8 +457,10 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= @@ -661,7 +687,11 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1 github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vmihailenco/msgpack/v5 v5.0.0-beta.9/go.mod h1:HVxBVPUK/+fZMonk4bi1islLa8V3cfnBug0+4dykPzo= @@ -951,6 +981,8 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= +nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= From 011e75ba35a457540d5aaa2ff13913d51f5cc0cd Mon Sep 17 00:00:00 2001 From: Tobias Schwarz Date: Wed, 10 Feb 2021 00:13:19 +0100 Subject: [PATCH 113/152] Update chain-upgrade-guide-040.md (#8326) Still a problem with `cat` - a tmp_genesis file needs to be created and then moved to the old location Co-authored-by: Amaury Co-authored-by: Cory --- docs/migrations/chain-upgrade-guide-040.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/migrations/chain-upgrade-guide-040.md b/docs/migrations/chain-upgrade-guide-040.md index abb9f975bddf..bce84966452a 100644 --- a/docs/migrations/chain-upgrade-guide-040.md +++ b/docs/migrations/chain-upgrade-guide-040.md @@ -87,7 +87,7 @@ software and restore to their latest snapshot before restarting their nodes. 1) If your chain is using IBC, make sure to add IBC initial genesis state to the genesis file. You can use the following command to add IBC initial genesis state to the genesis file. ```shell - cat new_v040_genesis.json | jq '.app_state |= . + {"ibc":{"client_genesis":{"clients":[],"clients_consensus":[],"create_localhost":false},"connection_genesis":{"connections":[],"client_connection_paths":[]},"channel_genesis":{"channels":[],"acknowledgements":[],"commitments":[],"receipts":[],"send_sequences":[],"recv_sequences":[],"ack_sequences":[]}},"transfer":{"port_id":"transfer","denom_traces":[],"params":{"send_enabled":false,"receive_enabled":false}},"capability":{"index":"1","owners":[]}}' > new_v040_genesis.json + cat new_v040_genesis.json | jq '.app_state |= . + {"ibc":{"client_genesis":{"clients":[],"clients_consensus":[],"create_localhost":false},"connection_genesis":{"connections":[],"client_connection_paths":[]},"channel_genesis":{"channels":[],"acknowledgements":[],"commitments":[],"receipts":[],"send_sequences":[],"recv_sequences":[],"ack_sequences":[]}},"transfer":{"port_id":"transfer","denom_traces":[],"params":{"send_enabled":false,"receive_enabled":false}},"capability":{"index":"1","owners":[]}}' > tmp_genesis.json && mv tmp_genesis.json new_v040_genesis.json ``` **Note:** This would add IBC state with IBC's `send_enabled: false` and `receive_enabled: false`. Make sure to update them to `true` in the above command if are planning to enable IBC transactions with chain upgrade. Otherwise you can do it via a governance proposal. From 41f3c050079d1dac10b836c1302680e76d60c77f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Feb 2021 08:29:06 +0000 Subject: [PATCH 114/152] build(deps): bump github.com/tendermint/tm-db from 0.6.3 to 0.6.4 (#8555) Bumps [github.com/tendermint/tm-db](https://github.com/tendermint/tm-db) from 0.6.3 to 0.6.4. - [Release notes](https://github.com/tendermint/tm-db/releases) - [Changelog](https://github.com/tendermint/tm-db/blob/master/CHANGELOG.md) - [Commits](https://github.com/tendermint/tm-db/compare/v0.6.3...v0.6.4) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 37fa821ac6bf..bd5d1d13125a 100644 --- a/go.mod +++ b/go.mod @@ -48,7 +48,7 @@ require ( github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 github.com/tendermint/go-amino v0.16.0 github.com/tendermint/tendermint v0.34.3 - github.com/tendermint/tm-db v0.6.3 + github.com/tendermint/tm-db v0.6.4 golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f google.golang.org/grpc v1.35.0 diff --git a/go.sum b/go.sum index 266ad810f42a..8333977c868e 100644 --- a/go.sum +++ b/go.sum @@ -678,6 +678,8 @@ github.com/tendermint/tendermint v0.34.3/go.mod h1:h57vnXeOlrdvvNFCqPBSaOrpOivl+ github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI= github.com/tendermint/tm-db v0.6.3 h1:ZkhQcKnB8/2jr5EaZwGndN4owkPsGezW2fSisS9zGbg= github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8= +github.com/tendermint/tm-db v0.6.4 h1:3N2jlnYQkXNQclQwd/eKV/NzlqPlfK21cpRRIx80XXQ= +github.com/tendermint/tm-db v0.6.4/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw= github.com/tidwall/gjson v1.6.1/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0= github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= From 926ef341bfb5d64c991164f8f1571ce154368ba7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Feb 2021 08:32:27 +0000 Subject: [PATCH 115/152] build(deps): bump JamesIves/github-pages-deploy-action from 3.7.1 to 4.0.0 (#8535) Bumps [JamesIves/github-pages-deploy-action](https://github.com/JamesIves/github-pages-deploy-action) from 3.7.1 to 4.0.0. - [Release notes](https://github.com/JamesIves/github-pages-deploy-action/releases) - [Commits](https://github.com/JamesIves/github-pages-deploy-action/compare/3.7.1...049a95c516cd5723d8cfde79dc7a79fcdcbd6c97) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 9c8fc8fbae0c..493d1c21c231 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -24,7 +24,7 @@ jobs: make build-docs LEDGER_ENABLED=false - name: Deploy 🚀 - uses: JamesIves/github-pages-deploy-action@3.7.1 + uses: JamesIves/github-pages-deploy-action@4.0.0 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} BRANCH: gh-pages From 7baf71549585a55b68ad0c6f4856c2e481ee7668 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Feb 2021 09:49:43 +0000 Subject: [PATCH 116/152] build(deps): bump github.com/spf13/cobra from 1.1.1 to 1.1.2 (#8554) Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.1.1 to 1.1.2. - [Release notes](https://github.com/spf13/cobra/releases) - [Changelog](https://github.com/spf13/cobra/blob/master/CHANGELOG.md) - [Commits](https://github.com/spf13/cobra/compare/v1.1.1...v1.1.2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index bd5d1d13125a..f0dd2a1a9389 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( github.com/rs/zerolog v1.20.0 github.com/spf13/afero v1.3.4 // indirect github.com/spf13/cast v1.3.1 - github.com/spf13/cobra v1.1.1 + github.com/spf13/cobra v1.1.2 github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.7.1 diff --git a/go.sum b/go.sum index 8333977c868e..b295f12d8065 100644 --- a/go.sum +++ b/go.sum @@ -627,6 +627,8 @@ github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tL github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.1.2 h1:frHO75w/dH7kEc+e2KYZZKY4+PLrp39OqI77oB8m0KQ= +github.com/spf13/cobra v1.1.2/go.mod h1:ZjwqWkCg0LnXvLRIfTLdB4Y/MCO3gMHHJ2KFxQZy4xE= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= From 9ca52f4202df61dd807e22451177ce11b8fb5072 Mon Sep 17 00:00:00 2001 From: billy rennekamp Date: Wed, 10 Feb 2021 10:52:57 +0100 Subject: [PATCH 117/152] Update cosmovisor.md (#8552) Co-authored-by: Alessio Treglia Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/run-node/cosmovisor.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/run-node/cosmovisor.md b/docs/run-node/cosmovisor.md index 56ee5f7fa7bb..99cb81e0cc45 100644 --- a/docs/run-node/cosmovisor.md +++ b/docs/run-node/cosmovisor.md @@ -1,10 +1,6 @@ # Cosmosvisor Quick Start -`cosmovisor` is a small process manager around Cosmos SDK binaries that uses the upgrade module to allow -for smooth and configurable management of upgrading binaries as a live chain is upgraded, and can be -used to simplify validator operations while doing upgrades or to make syncing a full node for genesis -simple. The `cosmovisor` program monitors the stdout of Cosmos SDK application's executable to look for -messages from the upgrade module indicating a pending or required upgrade and act appropriately. +`cosmovisor` is a small process manager around Cosmos SDK binaries that monitors the governance module via stdout to see if there's a chain upgrade proposal coming in. If it see a proposal that gets approved it can be run manually or automatically to download the new code, stop the node, run the migration script, replace the node binary, and start with the new genesis file. ## Installation From 065c1b39ce3ee543f860e20ff08ded549941123e Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Wed, 10 Feb 2021 12:27:06 -0500 Subject: [PATCH 118/152] Apply suggestions from code review Co-authored-by: Anil Kumar Kammari --- proto/cosmos/gov/v1beta1/tx.proto | 2 +- x/gov/client/cli/tx.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/proto/cosmos/gov/v1beta1/tx.proto b/proto/cosmos/gov/v1beta1/tx.proto index 25ae919370b0..8b68c4be45a4 100644 --- a/proto/cosmos/gov/v1beta1/tx.proto +++ b/proto/cosmos/gov/v1beta1/tx.proto @@ -73,7 +73,7 @@ message MsgVoteWeighted { // MsgVoteResponse defines the Msg/Vote response type. message MsgVoteResponse {} -// MsgVoteWeightedResponse defines the MsgVoteWeighted response type. +// MsgVoteWeightedResponse defines the Msg/VoteWeighted response type. message MsgVoteWeightedResponse {} // MsgDeposit defines a message to submit a deposit to an existing proposal. diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 6e1de14a077f..09aa6e5315a8 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -270,7 +270,7 @@ $ %s tx gov vote 1 yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05 --from mykey return err } - // Get voting address + // Get voter address from := clientCtx.GetFromAddress() // validate that the proposal id is a uint From dfc8dd813e041dfb21cc188ad597522f19a75927 Mon Sep 17 00:00:00 2001 From: Amaury Date: Wed, 10 Feb 2021 18:49:31 +0100 Subject: [PATCH 119/152] Add in-place store migrations (#8485) * Add 1st version of migrate * Put migration logic into Configurator * add test to bank store migration * add test for configurator * Error if no migration found * Remove RunMigrations from Configurator interface * Update spec * Rename folders * copy-paste from keys.go * Fix nil map * rename function * Update simapp/app.go Co-authored-by: Robert Zaremba * Update simapp/app_test.go Co-authored-by: Robert Zaremba * Adderss reviews * Fix tests * Update testutil/context.go Co-authored-by: Robert Zaremba * Update docs for ConsensusVersion * Rename to forVersion * Fix tests * Check error early * Return 1 for intiial version * Use MigrationKeeper * Fix test * Revert adding marshaler to Configurator * Godoc updates * Update docs Co-authored-by: Robert Zaremba Co-authored-by: Aaron Craelius --- simapp/app.go | 28 ++++++++- simapp/app_test.go | 89 ++++++++++++++++++++++++++- tests/mocks/types_module_module.go | 3 + testutil/context.go | 25 ++++++++ types/context_test.go | 17 +---- types/module/configurator.go | 75 +++++++++++++++++++++- types/module/module.go | 34 ++++++++++ x/auth/legacy/v040/store.go | 4 ++ x/auth/module.go | 3 + x/auth/vesting/module.go | 3 + x/authz/module.go | 3 + x/bank/keeper/migrations.go | 20 ++++++ x/bank/legacy/v040/keys.go | 47 ++++++++++++++ x/bank/legacy/v040/types.go | 5 -- x/bank/legacy/v042/keys.go | 50 +++++++++++++++ x/bank/legacy/v042/store.go | 38 ++++++++++++ x/bank/legacy/v042/store_test.go | 36 +++++++++++ x/bank/module.go | 6 ++ x/bank/spec/01_state.md | 2 +- x/capability/module.go | 3 + x/crisis/module.go | 3 + x/distribution/module.go | 3 + x/evidence/module.go | 3 + x/feegrant/module.go | 3 + x/genutil/module.go | 3 + x/gov/module.go | 3 + x/ibc/applications/transfer/module.go | 3 + x/ibc/core/module.go | 3 + x/mint/module.go | 3 + x/params/keeper/common_test.go | 24 +------- x/params/module.go | 3 + x/slashing/module.go | 3 + x/staking/module.go | 3 + x/upgrade/module.go | 3 + 34 files changed, 509 insertions(+), 45 deletions(-) create mode 100644 testutil/context.go create mode 100644 x/auth/legacy/v040/store.go create mode 100644 x/bank/keeper/migrations.go create mode 100644 x/bank/legacy/v040/keys.go delete mode 100644 x/bank/legacy/v040/types.go create mode 100644 x/bank/legacy/v042/keys.go create mode 100644 x/bank/legacy/v042/store.go create mode 100644 x/bank/legacy/v042/store_test.go diff --git a/simapp/app.go b/simapp/app.go index 23ced043d047..4db7d53d7755 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -198,6 +198,9 @@ type SimApp struct { // simulation manager sm *module.SimulationManager + + // the configurator + configurator module.Configurator } func init() { @@ -393,7 +396,8 @@ func NewSimApp( app.mm.RegisterInvariants(&app.CrisisKeeper) app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino) - app.mm.RegisterServices(module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter())) + app.configurator = module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter()) + app.mm.RegisterServices(app.configurator) // add test gRPC service for testing gRPC queries in isolation testdata.RegisterQueryServer(app.GRPCQueryRouter(), testdata.QueryImpl{}) @@ -598,6 +602,28 @@ func (app *SimApp) RegisterTendermintService(clientCtx client.Context) { tmservice.RegisterTendermintService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.interfaceRegistry) } +// RunMigrations performs in-place store migrations for all modules. This +// function MUST be only called by x/upgrade UpgradeHandler. +// +// `migrateFromVersions` is a map of moduleName to fromVersion (unit64), where +// fromVersion denotes the version from which we should migrate the module, the +// target version being the module's latest ConsensusVersion. +// +// Example: +// cfg := module.NewConfigurator(...) +// app.UpgradeKeeper.SetUpgradeHandler("store-migration", func(ctx sdk.Context, plan upgradetypes.Plan) { +// err := app.RunMigrations(ctx, module.MigrationMap{ +// "bank": 1, // Migrate x/bank from v1 to current x/bank's ConsensusVersion +// "staking": 8, // Migrate x/staking from v8 to current x/staking's ConsensusVersion +// }) +// if err != nil { +// panic(err) +// } +// }) +func (app *SimApp) RunMigrations(ctx sdk.Context, migrateFromVersions module.MigrationMap) error { + return app.mm.RunMigrations(ctx, app.configurator, migrateFromVersions) +} + // RegisterSwaggerAPI registers swagger route with API Server func RegisterSwaggerAPI(ctx client.Context, rtr *mux.Router) { statikFS, err := fs.New() diff --git a/simapp/app_test.go b/simapp/app_test.go index 6543f94fd437..2adcf2e7e8d2 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -6,10 +6,13 @@ import ( "testing" "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" dbm "github.com/tendermint/tm-db" - abci "github.com/tendermint/tendermint/abci/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" ) func TestSimAppExportAndBlockedAddrs(t *testing.T) { @@ -45,3 +48,87 @@ func TestGetMaccPerms(t *testing.T) { dup := GetMaccPerms() require.Equal(t, maccPerms, dup, "duplicated module account permissions differed from actual module account permissions") } + +func TestRunMigrations(t *testing.T) { + db := dbm.NewMemDB() + encCfg := MakeTestEncodingConfig() + app := NewSimApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{}) + + // Create a new configurator for the purpose of this test. + app.configurator = module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter()) + + testCases := []struct { + name string + moduleName string + forVersion uint64 + expRegErr bool // errors while registering migration + expRegErrMsg string + expRunErr bool // errors while running migration + expRunErrMsg string + expCalled int + }{ + { + "cannot register migration for version 0", + "bank", 0, + true, "module migration versions should start at 1: invalid version", false, "", 0, + }, + { + "throws error on RunMigrations if no migration registered for bank", + "", 1, + false, "", true, "no migrations found for module bank: not found", 0, + }, + { + "can register and run migration handler for x/bank", + "bank", 1, + false, "", false, "", 1, + }, + { + "cannot register migration handler for same module & forVersion", + "bank", 1, + true, "another migration for module bank and version 1 already exists: internal logic error", false, "", 0, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + var err error + + // Since it's very hard to test actual in-place store migrations in + // tests (due to the difficulty of maintaing multiple versions of a + // module), we're just testing here that the migration logic is + // called. + called := 0 + + if tc.moduleName != "" { + // Register migration for module from version `forVersion` to `forVersion+1`. + err = app.configurator.RegisterMigration(tc.moduleName, tc.forVersion, func(sdk.Context) error { + called++ + + return nil + }) + + if tc.expRegErr { + require.EqualError(t, err, tc.expRegErrMsg) + + return + } + } + require.NoError(t, err) + + err = app.RunMigrations( + app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}), + module.MigrationMap{ + "auth": 1, "authz": 1, "bank": 1, "staking": 1, "mint": 1, "distribution": 1, + "slashing": 1, "gov": 1, "params": 1, "ibc": 1, "upgrade": 1, "vesting": 1, + "feegrant": 1, "transfer": 1, "evidence": 1, "crisis": 1, "genutil": 1, "capability": 1, + }, + ) + if tc.expRunErr { + require.EqualError(t, err, tc.expRunErrMsg) + } else { + require.NoError(t, err) + require.Equal(t, tc.expCalled, called) + } + }) + } +} diff --git a/tests/mocks/types_module_module.go b/tests/mocks/types_module_module.go index 41ded4d7a2c0..0d00584ab9a8 100644 --- a/tests/mocks/types_module_module.go +++ b/tests/mocks/types_module_module.go @@ -492,6 +492,9 @@ func (m *MockAppModule) ExportGenesis(arg0 types0.Context, arg1 codec.JSONMarsha return ret0 } +// ConsensusVersion mocks base method +func (m *MockAppModule) ConsensusVersion() uint64 { return 1 } + // ExportGenesis indicates an expected call of ExportGenesis func (mr *MockAppModuleMockRecorder) ExportGenesis(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() diff --git a/testutil/context.go b/testutil/context.go new file mode 100644 index 000000000000..2fb9865a2696 --- /dev/null +++ b/testutil/context.go @@ -0,0 +1,25 @@ +package testutil + +import ( + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + dbm "github.com/tendermint/tm-db" + + "github.com/cosmos/cosmos-sdk/store" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// DefaultContext creates a sdk.Context with a fresh MemDB that can be used in tests. +func DefaultContext(key sdk.StoreKey, tkey sdk.StoreKey) sdk.Context { + db := dbm.NewMemDB() + cms := store.NewCommitMultiStore(db) + cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) + cms.MountStoreWithDB(tkey, sdk.StoreTypeTransient, db) + err := cms.LoadLatestVersion() + if err != nil { + panic(err) + } + ctx := sdk.NewContext(cms, tmproto.Header{}, false, log.NewNopLogger()) + + return ctx +} diff --git a/types/context_test.go b/types/context_test.go index 018bd6a25792..4af5d8390f2f 100644 --- a/types/context_test.go +++ b/types/context_test.go @@ -8,13 +8,11 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/suite" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - dbm "github.com/tendermint/tm-db" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/cosmos/cosmos-sdk/store" "github.com/cosmos/cosmos-sdk/tests/mocks" + "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/types" ) @@ -26,15 +24,6 @@ func TestContextTestSuite(t *testing.T) { suite.Run(t, new(contextTestSuite)) } -func (s *contextTestSuite) defaultContext(key types.StoreKey) types.Context { - db := dbm.NewMemDB() - cms := store.NewCommitMultiStore(db) - cms.MountStoreWithDB(key, types.StoreTypeIAVL, db) - s.Require().NoError(cms.LoadLatestVersion()) - ctx := types.NewContext(cms, tmproto.Header{}, false, log.NewNopLogger()) - return ctx -} - func (s *contextTestSuite) TestCacheContext() { key := types.NewKVStoreKey(s.T().Name() + "_TestCacheContext") k1 := []byte("hello") @@ -42,7 +31,7 @@ func (s *contextTestSuite) TestCacheContext() { k2 := []byte("key") v2 := []byte("value") - ctx := s.defaultContext(key) + ctx := testutil.DefaultContext(key, types.NewTransientStoreKey("transient_"+s.T().Name())) store := ctx.KVStore(key) store.Set(k1, v1) s.Require().Equal(v1, store.Get(k1)) @@ -64,7 +53,7 @@ func (s *contextTestSuite) TestCacheContext() { func (s *contextTestSuite) TestLogContext() { key := types.NewKVStoreKey(s.T().Name()) - ctx := s.defaultContext(key) + ctx := testutil.DefaultContext(key, types.NewTransientStoreKey("transient_"+s.T().Name())) ctrl := gomock.NewController(s.T()) s.T().Cleanup(ctrl.Finish) diff --git a/types/module/configurator.go b/types/module/configurator.go index d561dd9eef0d..0e766df2a13d 100644 --- a/types/module/configurator.go +++ b/types/module/configurator.go @@ -1,6 +1,11 @@ package module -import "github.com/gogo/protobuf/grpc" +import ( + "github.com/gogo/protobuf/grpc" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) // Configurator provides the hooks to allow modules to configure and register // their services in the RegisterServices method. It is designed to eventually @@ -15,16 +20,34 @@ type Configurator interface { // QueryServer returns a grpc.Server instance which allows registering services // that will be exposed as gRPC services as well as ABCI query handlers. QueryServer() grpc.Server + + // RegisterMigration registers an in-place store migration for a module. The + // handler is a migration script to perform in-place migrations from version + // `forVersion` to version `forVersion+1`. + // + // EACH TIME a module's ConsensusVersion increments, a new migration MUST + // be registered using this function. If a migration handler is missing for + // a particular function, the upgrade logic (see RunMigrations function) + // will panic. If the ConsensusVersion bump does not introduce any store + // changes, then a no-op function must be registered here. + RegisterMigration(moduleName string, forVersion uint64, handler MigrationHandler) error } type configurator struct { msgServer grpc.Server queryServer grpc.Server + + // migrations is a map of moduleName -> forVersion -> migration script handler + migrations map[string]map[uint64]MigrationHandler } // NewConfigurator returns a new Configurator instance func NewConfigurator(msgServer grpc.Server, queryServer grpc.Server) Configurator { - return configurator{msgServer: msgServer, queryServer: queryServer} + return configurator{ + msgServer: msgServer, + queryServer: queryServer, + migrations: map[string]map[uint64]MigrationHandler{}, + } } var _ Configurator = configurator{} @@ -38,3 +61,51 @@ func (c configurator) MsgServer() grpc.Server { func (c configurator) QueryServer() grpc.Server { return c.queryServer } + +// RegisterMigration implements the Configurator.RegisterMigration method +func (c configurator) RegisterMigration(moduleName string, forVersion uint64, handler MigrationHandler) error { + if forVersion == 0 { + return sdkerrors.Wrap(sdkerrors.ErrInvalidVersion, "module migration versions should start at 1") + } + + if c.migrations[moduleName] == nil { + c.migrations[moduleName] = map[uint64]MigrationHandler{} + } + + if c.migrations[moduleName][forVersion] != nil { + return sdkerrors.Wrapf(sdkerrors.ErrLogic, "another migration for module %s and version %d already exists", moduleName, forVersion) + } + + c.migrations[moduleName][forVersion] = handler + + return nil +} + +// runModuleMigrations runs all in-place store migrations for one given module from a +// version to another version. +func (c configurator) runModuleMigrations(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error { + // No-op if toVersion is the initial version. + if toVersion <= 1 { + return nil + } + + moduleMigrationsMap, found := c.migrations[moduleName] + if !found { + return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no migrations found for module %s", moduleName) + } + + // Run in-place migrations for the module sequentially until toVersion. + for i := fromVersion; i < toVersion; i++ { + migrateFn, found := moduleMigrationsMap[i] + if !found { + return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no migration found for module %s from version %d to version %d", moduleName, i, i+1) + } + + err := migrateFn(ctx) + if err != nil { + return err + } + } + + return nil +} diff --git a/types/module/module.go b/types/module/module.go index 2379c93d5ebd..58bb4927b29a 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -40,6 +40,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) //__________________________________________________________________________________________ @@ -174,6 +175,12 @@ type AppModule interface { // RegisterServices allows a module to register services RegisterServices(Configurator) + // ConsensusVersion is a sequence number for state-breaking change of the + // module. It should be incremented on each consensus-breaking change + // introduced by the module. To avoid wrong/empty versions, the initial version + // should be set to 1. + ConsensusVersion() uint64 + // ABCI BeginBlock(sdk.Context, abci.RequestBeginBlock) EndBlock(sdk.Context, abci.RequestEndBlock) []abci.ValidatorUpdate @@ -208,6 +215,9 @@ func (gam GenesisOnlyAppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Que // RegisterServices registers all services. func (gam GenesisOnlyAppModule) RegisterServices(Configurator) {} +// ConsensusVersion implements AppModule/ConsensusVersion. +func (gam GenesisOnlyAppModule) ConsensusVersion() uint64 { return 1 } + // BeginBlock returns an empty module begin-block func (gam GenesisOnlyAppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {} @@ -328,6 +338,30 @@ func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) map[st return genesisData } +// MigrationHandler is the migration function that each module registers. +type MigrationHandler func(store sdk.Context) error + +// MigrationMap is a map of moduleName -> version, where version denotes the +// version from which we should perform the migration for each module. +type MigrationMap map[string]uint64 + +// RunMigrations performs in-place store migrations for all modules. +func (m Manager) RunMigrations(ctx sdk.Context, cfg Configurator, migrateFromVersions MigrationMap) error { + c, ok := cfg.(configurator) + if !ok { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expected %T, got %T", configurator{}, cfg) + } + + for moduleName, module := range m.Modules { + err := c.runModuleMigrations(ctx, moduleName, migrateFromVersions[moduleName], module.ConsensusVersion()) + if err != nil { + return err + } + } + + return nil +} + // BeginBlock performs begin block functionality for all modules. It creates a // child context with an event manager to aggregate events emitted from all // modules. diff --git a/x/auth/legacy/v040/store.go b/x/auth/legacy/v040/store.go new file mode 100644 index 000000000000..9fb81b60a749 --- /dev/null +++ b/x/auth/legacy/v040/store.go @@ -0,0 +1,4 @@ +package v040 + +// AddrLen defines a valid address length +const AddrLen = 20 diff --git a/x/auth/module.go b/x/auth/module.go index 73aa9a1066a9..9e4af71ff037 100644 --- a/x/auth/module.go +++ b/x/auth/module.go @@ -147,6 +147,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + // BeginBlock returns the begin blocker for the auth module. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/auth/vesting/module.go b/x/auth/vesting/module.go index 3cc579a40e37..259143469388 100644 --- a/x/auth/vesting/module.go +++ b/x/auth/vesting/module.go @@ -127,3 +127,6 @@ func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.Valid func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.RawMessage { return am.DefaultGenesis(cdc) } + +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/authz/module.go b/x/authz/module.go index 1bcd388e4df9..b39c02487fe0 100644 --- a/x/authz/module.go +++ b/x/authz/module.go @@ -152,6 +152,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {} // EndBlock does nothing diff --git a/x/bank/keeper/migrations.go b/x/bank/keeper/migrations.go new file mode 100644 index 000000000000..de6b61a9c2b6 --- /dev/null +++ b/x/bank/keeper/migrations.go @@ -0,0 +1,20 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + v042 "github.com/cosmos/cosmos-sdk/x/bank/legacy/v042" +) + +// MigrationKeeper is an interface that the keeper implements for handling +// in-place store migrations. +type MigrationKeeper interface { + // Migrate1 migrates the store from version 1 to 2. + Migrate1(ctx sdk.Context) error +} + +var _ MigrationKeeper = (*BaseKeeper)(nil) + +// Migrate1 implements MigrationKeeper.Migrate1 method. +func (keeper BaseKeeper) Migrate1(ctx sdk.Context) error { + return v042.MigrateStore(ctx, keeper.storeKey) +} diff --git a/x/bank/legacy/v040/keys.go b/x/bank/legacy/v040/keys.go new file mode 100644 index 000000000000..bd1035599164 --- /dev/null +++ b/x/bank/legacy/v040/keys.go @@ -0,0 +1,47 @@ +package v040 + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" +) + +const ( + // ModuleName defines the module name + ModuleName = "bank" + + // StoreKey defines the primary module store key + StoreKey = ModuleName + + // RouterKey defines the module's message routing key + RouterKey = ModuleName + + // QuerierRoute defines the module's query routing key + QuerierRoute = ModuleName +) + +// KVStore keys +var ( + BalancesPrefix = []byte("balances") + SupplyKey = []byte{0x00} + DenomMetadataPrefix = []byte{0x1} +) + +// DenomMetadataKey returns the denomination metadata key. +func DenomMetadataKey(denom string) []byte { + d := []byte(denom) + return append(DenomMetadataPrefix, d...) +} + +// AddressFromBalancesStore returns an account address from a balances prefix +// store. The key must not contain the perfix BalancesPrefix as the prefix store +// iterator discards the actual prefix. +func AddressFromBalancesStore(key []byte) sdk.AccAddress { + addr := key[:v040auth.AddrLen] + if len(addr) != v040auth.AddrLen { + panic(fmt.Sprintf("unexpected account address key length; got: %d, expected: %d", len(addr), v040auth.AddrLen)) + } + + return sdk.AccAddress(addr) +} diff --git a/x/bank/legacy/v040/types.go b/x/bank/legacy/v040/types.go deleted file mode 100644 index 04ac05f9fcd3..000000000000 --- a/x/bank/legacy/v040/types.go +++ /dev/null @@ -1,5 +0,0 @@ -package v040 - -const ( - ModuleName = "bank" -) diff --git a/x/bank/legacy/v042/keys.go b/x/bank/legacy/v042/keys.go new file mode 100644 index 000000000000..8d718b1c5d3c --- /dev/null +++ b/x/bank/legacy/v042/keys.go @@ -0,0 +1,50 @@ +package v042 + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" +) + +const ( + // ModuleName defines the module name + ModuleName = "bank" + + // StoreKey defines the primary module store key + StoreKey = ModuleName + + // RouterKey defines the module's message routing key + RouterKey = ModuleName + + // QuerierRoute defines the module's query routing key + QuerierRoute = ModuleName +) + +// KVStore keys +var ( + // BalancesPrefix is the for the account balances store. We use a byte + // (instead of say `[]]byte("balances")` to save some disk space). + BalancesPrefix = []byte{0x02} + SupplyKey = []byte{0x00} + DenomMetadataPrefix = []byte{0x1} +) + +// DenomMetadataKey returns the denomination metadata key. +func DenomMetadataKey(denom string) []byte { + d := []byte(denom) + return append(DenomMetadataPrefix, d...) +} + +// AddressFromBalancesStore returns an account address from a balances prefix +// store. The key must not contain the perfix BalancesPrefix as the prefix store +// iterator discards the actual prefix. +func AddressFromBalancesStore(key []byte) sdk.AccAddress { + addrLen := key[0] + addr := key[1 : addrLen+1] + + return sdk.AccAddress(addr) +} + +// CreateAccountBalancesPrefix creates the prefix for an account's balances. +func CreateAccountBalancesPrefix(addr []byte) []byte { + return append(BalancesPrefix, address.MustLengthPrefix(addr)...) +} diff --git a/x/bank/legacy/v042/store.go b/x/bank/legacy/v042/store.go new file mode 100644 index 000000000000..9295d8d2ff77 --- /dev/null +++ b/x/bank/legacy/v042/store.go @@ -0,0 +1,38 @@ +package v042 + +import ( + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" + v040bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v040" +) + +// MigrateStore performs in-place store migrations from v0.40 to v0.42. The +// migration includes: +// +// - Change addresses to be length-prefixed. +// - Change balances prefix to 1 byte +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error { + store := ctx.KVStore(storeKey) + + // old key is of format: + // prefix ("balances") || addrBytes (20 bytes) || denomBytes + // new key is of format + // prefix (0x02) || addrLen (1 byte) || addrBytes || denomBytes + oldStore := prefix.NewStore(store, v040bank.BalancesPrefix) + + oldStoreIter := oldStore.Iterator(nil, nil) + defer oldStoreIter.Close() + + for ; oldStoreIter.Valid(); oldStoreIter.Next() { + addr := v040bank.AddressFromBalancesStore(oldStoreIter.Key()) + denom := oldStoreIter.Key()[v040auth.AddrLen:] + newStoreKey := append(CreateAccountBalancesPrefix(addr), denom...) + + // Set new key on store. Values don't change. + store.Set(newStoreKey, oldStoreIter.Value()) + oldStore.Delete(oldStoreIter.Key()) + } + + return nil +} diff --git a/x/bank/legacy/v042/store_test.go b/x/bank/legacy/v042/store_test.go new file mode 100644 index 000000000000..e1b6a7987a04 --- /dev/null +++ b/x/bank/legacy/v042/store_test.go @@ -0,0 +1,36 @@ +package v042_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/testutil" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + v040bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v040" + v042bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v042" +) + +func TestStoreMigration(t *testing.T) { + bankKey := sdk.NewKVStoreKey("bank") + ctx := testutil.DefaultContext(bankKey, sdk.NewTransientStoreKey("transient_test")) + store := ctx.KVStore(bankKey) + + _, _, addr := testdata.KeyTestPubAddr() + denom := []byte("foo") + value := []byte("bar") + + oldKey := append(append(v040bank.BalancesPrefix, addr...), denom...) + store.Set(oldKey, value) + + err := v042bank.MigrateStore(ctx, bankKey) + require.NoError(t, err) + + newKey := append(v042bank.CreateAccountBalancesPrefix(addr), denom...) + // -7 because we replaced "balances" with 0x02, + // +1 because we added length-prefix to address. + require.Equal(t, len(oldKey)-7+1, len(newKey)) + require.Nil(t, store.Get(oldKey)) + require.Equal(t, value, store.Get(newKey)) +} diff --git a/x/bank/module.go b/x/bank/module.go index f271fa21975c..77bff6b73b61 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -100,6 +100,9 @@ type AppModule struct { func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + cfg.RegisterMigration(types.ModuleName, 0, func(ctx sdk.Context) error { + return am.keeper.(keeper.MigrationKeeper).Migrate1(ctx) + }) } // NewAppModule creates a new AppModule object @@ -151,6 +154,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 2 } + // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/bank/spec/01_state.md b/x/bank/spec/01_state.md index f744e2e779a1..6ca6b97e8fc1 100644 --- a/x/bank/spec/01_state.md +++ b/x/bank/spec/01_state.md @@ -7,5 +7,5 @@ order: 1 The `x/bank` module keeps state of two primary objects, account balances and the total supply of all balances. -- Balances: `[]byte("balances") | []byte(address) / []byte(balance.Denom) -> ProtocolBuffer(balance)` - Supply: `0x0 -> ProtocolBuffer(Supply)` +- Balances: `0x2 | byte(address length) | []byte(address) | []byte(balance.Denom) -> ProtocolBuffer(balance)` diff --git a/x/capability/module.go b/x/capability/module.go index 7957f57747d6..06bee1e2d029 100644 --- a/x/capability/module.go +++ b/x/capability/module.go @@ -136,6 +136,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(genState) } +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + // BeginBlock executes all ABCI BeginBlock logic respective to the capability module. func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/crisis/module.go b/x/crisis/module.go index 5d34c1ce28f9..66d829be810e 100644 --- a/x/crisis/module.go +++ b/x/crisis/module.go @@ -158,6 +158,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/distribution/module.go b/x/distribution/module.go index 034be6d9651d..0f0c0d358a91 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -161,6 +161,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + // BeginBlock returns the begin blocker for the distribution module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { BeginBlocker(ctx, req, am.keeper) diff --git a/x/evidence/module.go b/x/evidence/module.go index 4367fe8d58ce..9143e208e716 100644 --- a/x/evidence/module.go +++ b/x/evidence/module.go @@ -175,6 +175,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(ExportGenesis(ctx, am.keeper)) } +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + // BeginBlock executes all ABCI BeginBlock logic respective to the evidence module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { BeginBlocker(ctx, req, am.keeper) diff --git a/x/feegrant/module.go b/x/feegrant/module.go index 5f4ba807d895..31b08e6baab1 100644 --- a/x/feegrant/module.go +++ b/x/feegrant/module.go @@ -167,6 +167,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + // BeginBlock returns the begin blocker for the feegrant module. func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/genutil/module.go b/x/genutil/module.go index bfaeb0c59168..7a65531e453f 100644 --- a/x/genutil/module.go +++ b/x/genutil/module.go @@ -110,3 +110,6 @@ func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONMarshaler, data j func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.RawMessage { return am.DefaultGenesis(cdc) } + +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/gov/module.go b/x/gov/module.go index ad2191660c08..b72a4bfe5f5c 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -177,6 +177,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/ibc/applications/transfer/module.go b/x/ibc/applications/transfer/module.go index 67c736555b8a..25290d69a64c 100644 --- a/x/ibc/applications/transfer/module.go +++ b/x/ibc/applications/transfer/module.go @@ -145,6 +145,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + // BeginBlock implements the AppModule interface func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { } diff --git a/x/ibc/core/module.go b/x/ibc/core/module.go index 3371dc88a446..6527ab71eb2f 100644 --- a/x/ibc/core/module.go +++ b/x/ibc/core/module.go @@ -156,6 +156,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(ExportGenesis(ctx, *am.keeper)) } +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + // BeginBlock returns the begin blocker for the ibc module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { ibcclient.BeginBlocker(ctx, am.keeper.ClientKeeper) diff --git a/x/mint/module.go b/x/mint/module.go index 44e96ce74bda..d33043b36a2e 100644 --- a/x/mint/module.go +++ b/x/mint/module.go @@ -146,6 +146,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + // BeginBlock returns the begin blocker for the mint module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { BeginBlocker(ctx, am.keeper) diff --git a/x/params/keeper/common_test.go b/x/params/keeper/common_test.go index f6d567db11f7..3ba444173588 100644 --- a/x/params/keeper/common_test.go +++ b/x/params/keeper/common_test.go @@ -1,14 +1,9 @@ package keeper_test import ( - "github.com/tendermint/tendermint/libs/log" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - dbm "github.com/tendermint/tm-db" - - "github.com/cosmos/cosmos-sdk/simapp" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/store" + "github.com/cosmos/cosmos-sdk/simapp" + "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" ) @@ -18,7 +13,7 @@ func testComponents() (*codec.LegacyAmino, sdk.Context, sdk.StoreKey, sdk.StoreK legacyAmino := createTestCodec() mkey := sdk.NewKVStoreKey("test") tkey := sdk.NewTransientStoreKey("transient_test") - ctx := defaultContext(mkey, tkey) + ctx := testutil.DefaultContext(mkey, tkey) keeper := paramskeeper.NewKeeper(marshaler, legacyAmino, mkey, tkey) return legacyAmino, ctx, mkey, tkey, keeper @@ -37,16 +32,3 @@ func createTestCodec() *codec.LegacyAmino { cdc.RegisterConcrete(invalid{}, "test/invalid", nil) return cdc } - -func defaultContext(key sdk.StoreKey, tkey sdk.StoreKey) sdk.Context { - db := dbm.NewMemDB() - cms := store.NewCommitMultiStore(db) - cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) - cms.MountStoreWithDB(tkey, sdk.StoreTypeTransient, db) - err := cms.LoadLatestVersion() - if err != nil { - panic(err) - } - ctx := sdk.NewContext(cms, tmproto.Header{}, false, log.NewNopLogger()) - return ctx -} diff --git a/x/params/module.go b/x/params/module.go index b0a4584129ef..c1a115b210c1 100644 --- a/x/params/module.go +++ b/x/params/module.go @@ -139,6 +139,9 @@ func (am AppModule) ExportGenesis(_ sdk.Context, _ codec.JSONMarshaler) json.Raw return nil } +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/slashing/module.go b/x/slashing/module.go index 91ad472e90df..ba5cfb60adb9 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -159,6 +159,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + // BeginBlock returns the begin blocker for the slashing module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { BeginBlocker(ctx, req, am.keeper) diff --git a/x/staking/module.go b/x/staking/module.go index f2e422117476..48c67e6f5cd1 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -157,6 +157,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json return cdc.MustMarshalJSON(gs) } +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + // BeginBlock returns the begin blocker for the staking module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { BeginBlocker(ctx, am.keeper) diff --git a/x/upgrade/module.go b/x/upgrade/module.go index 4e4982a324cf..23311c22d5f3 100644 --- a/x/upgrade/module.go +++ b/x/upgrade/module.go @@ -120,6 +120,9 @@ func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.R return am.DefaultGenesis(cdc) } +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + // BeginBlock calls the upgrade module hooks // // CONTRACT: this is registered in BeginBlocker *before* all other modules' BeginBlock functions From bddbc131fd232a0c4c3acf402eb5880109c96281 Mon Sep 17 00:00:00 2001 From: SaReN Date: Thu, 11 Feb 2021 15:19:26 +0530 Subject: [PATCH 120/152] update pagination tests (#8565) --- types/query/filtered_pagination_test.go | 5 ++--- types/query/pagination_test.go | 20 +------------------- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/types/query/filtered_pagination_test.go b/types/query/filtered_pagination_test.go index 2622f7b8e7c8..e0685fbaf3b8 100644 --- a/types/query/filtered_pagination_test.go +++ b/types/query/filtered_pagination_test.go @@ -8,7 +8,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/address" "github.com/cosmos/cosmos-sdk/types/query" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -32,7 +31,7 @@ func (s *paginationTestSuite) TestFilteredPaginations() { acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) s.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, balances)) - store := ctx.KVStore(app.GetKey(authtypes.StoreKey)) + store := ctx.KVStore(app.GetKey(types.StoreKey)) // verify pagination with limit > total values pageReq := &query.PageRequest{Key: nil, Limit: 5, CountTotal: true} @@ -110,7 +109,7 @@ func ExampleFilteredPaginate() { } pageReq := &query.PageRequest{Key: nil, Limit: 1, CountTotal: true} - store := ctx.KVStore(app.GetKey(authtypes.StoreKey)) + store := ctx.KVStore(app.GetKey(types.StoreKey)) balancesStore := prefix.NewStore(store, types.BalancesPrefix) accountStore := prefix.NewStore(balancesStore, address.MustLengthPrefix(addr1)) diff --git a/types/query/pagination_test.go b/types/query/pagination_test.go index 18853e97cc69..74a7c959e4a2 100644 --- a/types/query/pagination_test.go +++ b/types/query/pagination_test.go @@ -19,9 +19,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/address" "github.com/cosmos/cosmos-sdk/types/query" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -192,7 +189,7 @@ func ExamplePaginate() { pageReq := &query.PageRequest{Key: nil, Limit: 1, CountTotal: true} request := types.NewQueryAllBalancesRequest(addr1, pageReq) balResult := sdk.NewCoins() - authStore := ctx.KVStore(app.GetKey(authtypes.StoreKey)) + authStore := ctx.KVStore(app.GetKey(types.StoreKey)) balancesStore := prefix.NewStore(authStore, types.BalancesPrefix) accountStore := prefix.NewStore(balancesStore, address.MustLengthPrefix(addr1)) pageRes, err := query.Paginate(accountStore, request.Pagination, func(key []byte, value []byte) error { @@ -222,20 +219,5 @@ func setupTest() (*simapp.SimApp, sdk.Context, codec.Marshaler) { ms.LoadLatestVersion() - maccPerms := simapp.GetMaccPerms() - maccPerms[holder] = nil - maccPerms[authtypes.Burner] = []string{authtypes.Burner} - maccPerms[authtypes.Minter] = []string{authtypes.Minter} - maccPerms[multiPerm] = []string{authtypes.Burner, authtypes.Minter, authtypes.Staking} - maccPerms[randomPerm] = []string{"random"} - app.AccountKeeper = authkeeper.NewAccountKeeper( - appCodec, app.GetKey(authtypes.StoreKey), app.GetSubspace(authtypes.ModuleName), - authtypes.ProtoBaseAccount, maccPerms, - ) - app.BankKeeper = bankkeeper.NewBaseKeeper( - appCodec, app.GetKey(authtypes.StoreKey), app.AccountKeeper, - app.GetSubspace(types.ModuleName), make(map[string]bool), - ) - return app, ctx, appCodec } From 2154815f4cac8b6d755406f1cf2b429d08ea09f9 Mon Sep 17 00:00:00 2001 From: MD Aleem <72057206+aleem1314@users.noreply.github.com> Date: Thu, 11 Feb 2021 22:26:37 +0530 Subject: [PATCH 121/152] x/authz specs (#8499) * init * init * add events * add state & messages * WIP * update Readme * WIP * Update x/README.md Co-authored-by: Alessio Treglia * Update x/authz/spec/README.md Co-authored-by: Amaury * Update x/authz/spec/02_state.md Co-authored-by: Amaury * Update x/authz/spec/01_concepts.md Co-authored-by: Amaury * review changes * Update x/authz/spec/01_concepts.md Co-authored-by: Amaury * Update x/authz/spec/02_state.md Co-authored-by: Amaury * Update x/authz/spec/01_concepts.md Co-authored-by: Cory * Update x/authz/spec/04_events.md Co-authored-by: Cory * Update x/authz/spec/04_events.md Co-authored-by: Cory * Update x/authz/spec/README.md Co-authored-by: Cory Co-authored-by: Alessio Treglia Co-authored-by: Amaury Co-authored-by: Cory --- x/README.md | 1 + x/authz/spec/01_concepts.md | 37 ++++++++++++++++++++++++++++++++ x/authz/spec/02_state.md | 14 +++++++++++++ x/authz/spec/03_messages.md | 42 +++++++++++++++++++++++++++++++++++++ x/authz/spec/04_events.md | 28 +++++++++++++++++++++++++ x/authz/spec/README.md | 26 +++++++++++++++++++++++ 6 files changed, 148 insertions(+) create mode 100644 x/authz/spec/01_concepts.md create mode 100644 x/authz/spec/02_state.md create mode 100644 x/authz/spec/03_messages.md create mode 100644 x/authz/spec/04_events.md create mode 100644 x/authz/spec/README.md diff --git a/x/README.md b/x/README.md index 3be56a3de605..e90ee59cebcb 100644 --- a/x/README.md +++ b/x/README.md @@ -8,6 +8,7 @@ parent: Here are some production-grade modules that can be used in Cosmos SDK applications, along with their respective documentation: - [Auth](auth/spec/README.md) - Authentication of accounts and transactions for Cosmos SDK application. +- [Authz](authz/spec/README.md) - Authorization for accounts to perform actions on behalf of other accounts. - [Bank](bank/spec/README.md) - Token transfer functionalities. - [Capability](capability/spec/README.md) - Object capability implementation. - [Crisis](crisis/spec/README.md) - Halting the blockchain under certain circumstances (e.g. if an invariant is broken). diff --git a/x/authz/spec/01_concepts.md b/x/authz/spec/01_concepts.md new file mode 100644 index 000000000000..0f5e482f1619 --- /dev/null +++ b/x/authz/spec/01_concepts.md @@ -0,0 +1,37 @@ + + +# Concepts + +## Authorization +Any concrete type of authorization defined in the `x/authz` module must fulfill the `Authorization` interface outlined below. Authorizations determine exactly what privileges are granted. They are extensible and can be defined for any Msg service method even outside of the module where the Msg method is defined. Authorizations use the new `ServiceMsg` type from [ADR 031](../../../architecture/adr-031-msg-service.md). + + ++++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/x/authz/types/authorizations.go#L15-L24 + + +## Built-in Authorizations + +Cosmos-SDK `x/authz` module comes with following authorization types + +### SendAuthorization + +`SendAuthorization` implements `Authorization` interface for the `cosmos.bank.v1beta1.Msg/Send` ServiceMsg, that takes a `SpendLimit` and updates it down to zero. + ++++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/proto/cosmos/authz/v1beta1/authz.proto#L12-L19 + ++++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/x/authz/types/send_authorization.go#L23-L45 + +- `spent_limit` keeps track of how many coins left in the authorization. + + +### GenericAuthorization + +`GenericAuthorization` implements the `Authorization` interface, that gives unrestricted permission to execute the provided ServiceMsg on behalf of granter's account. + ++++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/proto/cosmos/authz/v1beta1/authz.proto#L21-L30 + ++++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/x/authz/types/generic_authorization.go#L20-L28 + +- `method_name` holds ServiceMsg type. diff --git a/x/authz/spec/02_state.md b/x/authz/spec/02_state.md new file mode 100644 index 000000000000..3afc5eddbafb --- /dev/null +++ b/x/authz/spec/02_state.md @@ -0,0 +1,14 @@ + + +# State + +## AuthorizationGrant + +Authorizations are identified by combining granter address (the address bytes of the granter), grantee address (the address bytes of the grantee) and ServiceMsg type (its method name). + +- AuthorizationGrant: `0x01 | granter_address_len (1 byte) | granter_address_bytes | grantee_address_len (1 byte) | grantee_address_bytes | msgType_bytes-> ProtocolBuffer(AuthorizationGrant)` + + ++++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/proto/cosmos/authz/v1beta1/authz.proto#L32-L37 diff --git a/x/authz/spec/03_messages.md b/x/authz/spec/03_messages.md new file mode 100644 index 000000000000..9b3cffa35c24 --- /dev/null +++ b/x/authz/spec/03_messages.md @@ -0,0 +1,42 @@ + + +# Messages + +In this section we describe the processing of messages for the authz module. + +## Msg/GrantAuthorization + +An authorization-grant is created using the `MsgGrantAuthorization` message. + ++++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/proto/cosmos/authz/v1beta1/tx.proto#L27-L35 + +This message is expected to fail if: + +- both granter & grantee have same address. +- provided `Expiration` time less than current unix timestamp. +- provided `Authorization` is not implemented. + +## Msg/RevokeAuthorization + +An allowed authorization can be removed with `MsgRevokeAuthorization` message. + ++++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/proto/cosmos/authz/v1beta1/tx.proto#L53-L59 + +This message is expected to fail if: + +- both granter & grantee have same address. +- provided `MethodName` is empty. + +## Msg/ExecAuthorizedRequest + +When a grantee wants to execute transaction on behalf of a granter, it must send MsgExecAuthorizedRequest. + ++++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/proto/cosmos/authz/v1beta1/tx.proto#L42-L48 + +This message is expected to fail if: + +- authorization not implemented for the provided msg. +- grantee don't have permission to run transaction. +- if granted authorization is expired. \ No newline at end of file diff --git a/x/authz/spec/04_events.md b/x/authz/spec/04_events.md new file mode 100644 index 000000000000..4d0a9858af7f --- /dev/null +++ b/x/authz/spec/04_events.md @@ -0,0 +1,28 @@ + + +# Events + +The authz module emits the following events: + +## Keeper + +### GrantAuthorization + +| Type | Attribute Key | Attribute Value | +|----------------------|-------------------|--------------------| +| grant-authorization | module | authz | +| grant-authorization | grant-type | {msgType} | +| grant-authorization | granter | {granterAddress} | +| grant-authorization | grantee | {granteeAddress} | + + +### RevokeAuthorization + +| Type | Attribute Key | Attribute Value | +|----------------------|-------------------|--------------------| +| revoke-authorization | module | authz | +| revoke-authorization | grant-type | {msgType} | +| revoke-authorization | granter | {granterAddress} | +| revoke-authorization | grantee | {granteeAddress} | diff --git a/x/authz/spec/README.md b/x/authz/spec/README.md new file mode 100644 index 000000000000..07ec1ba0c1e6 --- /dev/null +++ b/x/authz/spec/README.md @@ -0,0 +1,26 @@ + + +# `authz` + +## Contents + +## Abstract +`x/authz` is an implementation of a Cosmos SDK module, per [ADR 30](../../../architecture/adr-030-authz-module.md), that allows +granting arbitrary privileges from one account (the granter) to another account (the grantee). Authorizations must be granted for a particular Msg service method one by one using an implementation of the `Authorization` interface. + +1. **[Concept](01_concepts.md)** + - [Authorization](01_concepts.md#Authorization) + - [Built-in Authorizations](01_concepts.md#Built-in-Authorization) +2. **[State](02_state.md)** +3. **[Messages](03_messages.md)** + - [Msg/GrantAuthorization](03_messages.md#MsgGrantAuthorization) + - [Msg/RevokeAuthorization](03_messages.md#MsgRevokeAuthorization) + - [Msg/ExecAuthorized](03_messages.md#MsgExecAuthorized) +4. **[Events](04_events.md)** + - [Keeper](04_events.md#Keeper) + From 090411a7b5ddd6165f741c7b41b82089dda8947d Mon Sep 17 00:00:00 2001 From: Riccardo Montagnin Date: Fri, 12 Feb 2021 12:52:03 +0100 Subject: [PATCH 122/152] Removed GetValidator caching to fix concurrency error (#8546) * Removed GetValidator caching to fix concurrency error * Fixed linting and added CHANGELOG entry * Moved benchmark test into its own file * Moved CHANGELOG entry to bug fix * Update CHANGELOG.md Co-authored-by: Cory Co-authored-by: Amaury Co-authored-by: Cory Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- CHANGELOG.md | 1 + x/staking/keeper/keeper.go | 4 --- x/staking/keeper/validator.go | 39 ------------------------ x/staking/keeper/validator_bench_test.go | 29 ++++++++++++++++++ x/staking/keeper/validator_test.go | 11 ++++--- x/staking/teststaking/validator.go | 2 +- 6 files changed, 37 insertions(+), 49 deletions(-) create mode 100644 x/staking/keeper/validator_bench_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index e745b57961ec..190f39cac6bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (client/keys) [\#8436](https://github.com/cosmos/cosmos-sdk/pull/8436) Fix key migration issue * (server) [\#8481](https://github.com/cosmos/cosmos-sdk/pull/8481) Don't create files when running `{appd} tendermint show-*` subcommands +* (x/staking) [\#8546](https://github.com/cosmos/cosmos-sdk/pull/8546) Fix caching bug where concurrent calls to GetValidator could cause a node to crash ## [v0.40.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.1) - 2021-01-19 diff --git a/x/staking/keeper/keeper.go b/x/staking/keeper/keeper.go index 74d85a645bf7..81613d92bca9 100644 --- a/x/staking/keeper/keeper.go +++ b/x/staking/keeper/keeper.go @@ -12,8 +12,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/staking/types" ) -const aminoCacheSize = 500 - // Implements ValidatorSet interface var _ types.ValidatorSet = Keeper{} @@ -28,7 +26,6 @@ type Keeper struct { bankKeeper types.BankKeeper hooks types.StakingHooks paramstore paramtypes.Subspace - validatorCache map[string]cachedValidator validatorCacheList *list.List } @@ -58,7 +55,6 @@ func NewKeeper( bankKeeper: bk, paramstore: ps, hooks: nil, - validatorCache: make(map[string]cachedValidator, aminoCacheSize), validatorCacheList: list.New(), } } diff --git a/x/staking/keeper/validator.go b/x/staking/keeper/validator.go index 9fa6a0ca0a0b..0253c197aed3 100644 --- a/x/staking/keeper/validator.go +++ b/x/staking/keeper/validator.go @@ -10,22 +10,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/staking/types" ) -// Cache the amino decoding of validators, as it can be the case that repeated slashing calls -// cause many calls to GetValidator, which were shown to throttle the state machine in our -// simulation. Note this is quite biased though, as the simulator does more slashes than a -// live chain should, however we require the slashing to be fast as noone pays gas for it. -type cachedValidator struct { - val types.Validator - marshalled string // marshalled amino bytes for the validator object (not operator address) -} - -func newCachedValidator(val types.Validator, marshalled string) cachedValidator { - return cachedValidator{ - val: val, - marshalled: marshalled, - } -} - // get a single validator func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator types.Validator, found bool) { store := ctx.KVStore(k.storeKey) @@ -35,30 +19,7 @@ func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator ty return validator, false } - // If these amino encoded bytes are in the cache, return the cached validator - strValue := string(value) - if val, ok := k.validatorCache[strValue]; ok { - valToReturn := val.val - // Doesn't mutate the cache's value - valToReturn.OperatorAddress = addr.String() - - return valToReturn, true - } - - // amino bytes weren't found in cache, so amino unmarshal and add it to the cache - validator = types.MustUnmarshalValidator(k.cdc, value) - cachedVal := newCachedValidator(validator, strValue) - k.validatorCache[strValue] = newCachedValidator(validator, strValue) - k.validatorCacheList.PushBack(cachedVal) - - // if the cache is too big, pop off the last element from it - if k.validatorCacheList.Len() > aminoCacheSize { - valToRemove := k.validatorCacheList.Remove(k.validatorCacheList.Front()).(cachedValidator) - delete(k.validatorCache, valToRemove.marshalled) - } - validator = types.MustUnmarshalValidator(k.cdc, value) - return validator, true } diff --git a/x/staking/keeper/validator_bench_test.go b/x/staking/keeper/validator_bench_test.go new file mode 100644 index 000000000000..54a616c90e50 --- /dev/null +++ b/x/staking/keeper/validator_bench_test.go @@ -0,0 +1,29 @@ +package keeper_test + +import "testing" + +func BenchmarkGetValidator(b *testing.B) { + // 900 is the max number we are allowed to use in order to avoid simapp.CreateTestPubKeys + // panic: encoding/hex: odd length hex string + var powersNumber = 900 + + var totalPower int64 = 0 + var powers = make([]int64, powersNumber) + for i := range powers { + powers[i] = int64(i) + totalPower += int64(i) + } + + app, ctx, _, valAddrs, vals := initValidators(b, totalPower, len(powers), powers) + + for _, validator := range vals { + app.StakingKeeper.SetValidator(ctx, validator) + } + + b.ResetTimer() + for n := 0; n < b.N; n++ { + for _, addr := range valAddrs { + _, _ = app.StakingKeeper.GetValidator(ctx, addr) + } + } +} diff --git a/x/staking/keeper/validator_test.go b/x/staking/keeper/validator_test.go index ae98c177ef30..869644070507 100644 --- a/x/staking/keeper/validator_test.go +++ b/x/staking/keeper/validator_test.go @@ -19,13 +19,13 @@ import ( "github.com/cosmos/cosmos-sdk/x/staking/types" ) -func newMonikerValidator(t *testing.T, operator sdk.ValAddress, pubKey cryptotypes.PubKey, moniker string) types.Validator { +func newMonikerValidator(t testing.TB, operator sdk.ValAddress, pubKey cryptotypes.PubKey, moniker string) types.Validator { v, err := types.NewValidator(operator, pubKey, types.Description{Moniker: moniker}) require.NoError(t, err) return v } -func bootstrapValidatorTest(t *testing.T, power int64, numAddrs int) (*simapp.SimApp, sdk.Context, []sdk.AccAddress, []sdk.ValAddress) { +func bootstrapValidatorTest(t testing.TB, power int64, numAddrs int) (*simapp.SimApp, sdk.Context, []sdk.AccAddress, []sdk.ValAddress) { _, app, ctx := createTestInput() addrDels, addrVals := generateAddresses(app, ctx, numAddrs) @@ -43,12 +43,13 @@ func bootstrapValidatorTest(t *testing.T, power int64, numAddrs int) (*simapp.Si return app, ctx, addrDels, addrVals } -func initValidators(t *testing.T, power int64, numAddrs int, powers []int64) (*simapp.SimApp, sdk.Context, []sdk.AccAddress, []sdk.ValAddress, []types.Validator) { - app, ctx, addrs, valAddrs := bootstrapValidatorTest(t, 1000, 20) +func initValidators(t testing.TB, power int64, numAddrs int, powers []int64) (*simapp.SimApp, sdk.Context, []sdk.AccAddress, []sdk.ValAddress, []types.Validator) { + app, ctx, addrs, valAddrs := bootstrapValidatorTest(t, power, numAddrs) + pks := simapp.CreateTestPubKeys(numAddrs) vs := make([]types.Validator, len(powers)) for i, power := range powers { - vs[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) + vs[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), pks[i]) tokens := sdk.TokensFromConsensusPower(power) vs[i], _ = vs[i].AddTokensFromDel(tokens) } diff --git a/x/staking/teststaking/validator.go b/x/staking/teststaking/validator.go index 901395d76e92..71459581f0e6 100644 --- a/x/staking/teststaking/validator.go +++ b/x/staking/teststaking/validator.go @@ -11,7 +11,7 @@ import ( ) // NewValidator is a testing helper method to create validators in tests -func NewValidator(t *testing.T, operator sdk.ValAddress, pubKey cryptotypes.PubKey) types.Validator { +func NewValidator(t testing.TB, operator sdk.ValAddress, pubKey cryptotypes.PubKey) types.Validator { v, err := types.NewValidator(operator, pubKey, types.Description{}) require.NoError(t, err) return v From 591e46f35c420ae36b0c952f9299decfa39d22e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Feb 2021 12:31:21 +0000 Subject: [PATCH 123/152] build(deps): bump github.com/tendermint/tendermint from 0.34.3 to 0.34.4 (#8573) Bumps [github.com/tendermint/tendermint](https://github.com/tendermint/tendermint) from 0.34.3 to 0.34.4. - [Release notes](https://github.com/tendermint/tendermint/releases) - [Changelog](https://github.com/tendermint/tendermint/blob/v0.34.4/CHANGELOG.md) - [Commits](https://github.com/tendermint/tendermint/compare/v0.34.3...v0.34.4) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f0dd2a1a9389..9550fe1d419e 100644 --- a/go.mod +++ b/go.mod @@ -47,7 +47,7 @@ require ( github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2 github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 github.com/tendermint/go-amino v0.16.0 - github.com/tendermint/tendermint v0.34.3 + github.com/tendermint/tendermint v0.34.4 github.com/tendermint/tm-db v0.6.4 golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f diff --git a/go.sum b/go.sum index b295f12d8065..61325b3388aa 100644 --- a/go.sum +++ b/go.sum @@ -599,6 +599,8 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sasha-s/go-deadlock v0.2.0 h1:lMqc+fUb7RrFS3gQLtoQsJ7/6TV/pAIFvBsqX73DK8Y= github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10= +github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa h1:0U2s5loxrTy6/VgfVoLuVLFJcURKLH49ie0zSch7gh4= +github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -675,8 +677,8 @@ github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoM github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4= github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg= github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= -github.com/tendermint/tendermint v0.34.3 h1:9yEsf3WO5VAwPVwrmM+RffDMiijmNfWaBwNttHm0q5w= -github.com/tendermint/tendermint v0.34.3/go.mod h1:h57vnXeOlrdvvNFCqPBSaOrpOivl+2swWEtlUAqStYE= +github.com/tendermint/tendermint v0.34.4 h1:E7qkvFGx27d8ugVLiAY2iWP6DL5cep3l/mpTaWKHyBA= +github.com/tendermint/tendermint v0.34.4/go.mod h1:JVuu3V1ZexOaZG8VJMRl8lnfrGw6hEB2TVnoUwKRbss= github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI= github.com/tendermint/tm-db v0.6.3 h1:ZkhQcKnB8/2jr5EaZwGndN4owkPsGezW2fSisS9zGbg= github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8= From fc6c678bd25a34ee295388aeb5f2d11672fe461c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Feb 2021 10:19:07 -0300 Subject: [PATCH 124/152] build(deps): bump github.com/spf13/cobra from 1.1.2 to 1.1.3 (#8566) Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.1.2 to 1.1.3. - [Release notes](https://github.com/spf13/cobra/releases) - [Changelog](https://github.com/spf13/cobra/blob/master/CHANGELOG.md) - [Commits](https://github.com/spf13/cobra/compare/v1.1.2...v1.1.3) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9550fe1d419e..1258bf1bebdd 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( github.com/rs/zerolog v1.20.0 github.com/spf13/afero v1.3.4 // indirect github.com/spf13/cast v1.3.1 - github.com/spf13/cobra v1.1.2 + github.com/spf13/cobra v1.1.3 github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.7.1 diff --git a/go.sum b/go.sum index 61325b3388aa..c6dd93072dbd 100644 --- a/go.sum +++ b/go.sum @@ -629,8 +629,8 @@ github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tL github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= -github.com/spf13/cobra v1.1.2 h1:frHO75w/dH7kEc+e2KYZZKY4+PLrp39OqI77oB8m0KQ= -github.com/spf13/cobra v1.1.2/go.mod h1:ZjwqWkCg0LnXvLRIfTLdB4Y/MCO3gMHHJ2KFxQZy4xE= +github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= +github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= From e4b2d75dc4d25da0afdc6bf53bb05ba61c99183b Mon Sep 17 00:00:00 2001 From: Prathyusha Lakkireddy Date: Fri, 12 Feb 2021 19:02:03 +0530 Subject: [PATCH 125/152] ibc : replace strings.Contains to bytes.Contains (#8574) Co-authored-by: SaReN Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- x/ibc/core/02-client/keeper/grpc_query.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x/ibc/core/02-client/keeper/grpc_query.go b/x/ibc/core/02-client/keeper/grpc_query.go index 6328e5de3b81..2134427729ae 100644 --- a/x/ibc/core/02-client/keeper/grpc_query.go +++ b/x/ibc/core/02-client/keeper/grpc_query.go @@ -1,6 +1,7 @@ package keeper import ( + "bytes" "context" "fmt" "sort" @@ -159,7 +160,7 @@ func (q Keeper) ConsensusStates(c context.Context, req *types.QueryConsensusStat pageRes, err := query.FilteredPaginate(store, req.Pagination, func(key, value []byte, accumulate bool) (bool, error) { // filter any metadata stored under consensus state key - if strings.Contains(string(key), "/") { + if bytes.Contains(key, []byte("/")) { return false, nil } From ac16c90e5ce28418ce868056e2e355d5da388769 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Fri, 12 Feb 2021 11:06:45 -0500 Subject: [PATCH 126/152] remove legacy rest endpoints as per @anilCSE --- x/gov/client/rest/rest.go | 7 ------- x/gov/client/rest/tx.go | 42 --------------------------------------- 2 files changed, 49 deletions(-) diff --git a/x/gov/client/rest/rest.go b/x/gov/client/rest/rest.go index 81fb21d050e2..f11798e96760 100644 --- a/x/gov/client/rest/rest.go +++ b/x/gov/client/rest/rest.go @@ -58,10 +58,3 @@ type VoteReq struct { Voter sdk.AccAddress `json:"voter" yaml:"voter"` // address of the voter Option string `json:"option" yaml:"option"` // option from OptionSet chosen by the voter } - -// WeightedVoteReq defines the properties of a vote request's body. -type WeightedVoteReq struct { - BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` - Voter sdk.AccAddress `json:"voter" yaml:"voter"` // address of the voter - Options string `json:"options" yaml:"options"` // weighted options from OptionSet chosen by the voter -} diff --git a/x/gov/client/rest/tx.go b/x/gov/client/rest/tx.go index b910cb7c84fb..284c67148170 100644 --- a/x/gov/client/rest/tx.go +++ b/x/gov/client/rest/tx.go @@ -22,7 +22,6 @@ func registerTxHandlers(clientCtx client.Context, r *mux.Router, phs []ProposalR r.HandleFunc("/gov/proposals", newPostProposalHandlerFn(clientCtx)).Methods("POST") r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits", RestProposalID), newDepositHandlerFn(clientCtx)).Methods("POST") r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes", RestProposalID), newVoteHandlerFn(clientCtx)).Methods("POST") - r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/weightedvotes", RestProposalID), newWeightedVoteHandlerFn(clientCtx)).Methods("POST") } func newPostProposalHandlerFn(clientCtx client.Context) http.HandlerFunc { @@ -126,44 +125,3 @@ func newVoteHandlerFn(clientCtx client.Context) http.HandlerFunc { tx.WriteGeneratedTxResponse(clientCtx, w, req.BaseReq, msg) } } - -func newWeightedVoteHandlerFn(clientCtx client.Context) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - strProposalID := vars[RestProposalID] - - if len(strProposalID) == 0 { - rest.WriteErrorResponse(w, http.StatusBadRequest, "proposalId required but not specified") - return - } - - proposalID, ok := rest.ParseUint64OrReturnBadRequest(w, strProposalID) - if !ok { - return - } - - var req WeightedVoteReq - if !rest.ReadRESTReq(w, r, clientCtx.LegacyAmino, &req) { - return - } - - req.BaseReq = req.BaseReq.Sanitize() - if !req.BaseReq.ValidateBasic(w) { - return - } - - // Figure out which vote options user chose - options, err := types.WeightedVoteOptionsFromString(gcutils.NormalizeWeightedVoteOptions(req.Options)) - if rest.CheckBadRequestError(w, err) { - return - } - - // create the message - msg := types.NewMsgVoteWeighted(req.Voter, proposalID, options) - if rest.CheckBadRequestError(w, msg.ValidateBasic()) { - return - } - - tx.WriteGeneratedTxResponse(clientCtx, w, req.BaseReq, msg) - } -} From 8847157a7363d6108de5050dc60ab21bb5553a29 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Fri, 12 Feb 2021 12:19:14 -0500 Subject: [PATCH 127/152] Update x/gov/client/utils/utils.go Co-authored-by: Marko --- x/gov/client/utils/utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/gov/client/utils/utils.go b/x/gov/client/utils/utils.go index c45b7980d3ef..0e0bf04de7db 100644 --- a/x/gov/client/utils/utils.go +++ b/x/gov/client/utils/utils.go @@ -26,7 +26,7 @@ func NormalizeVoteOption(option string) string { } } -// NormalizeWeightedVoteOptions - normalize normalize vote options param string +// NormalizeWeightedVoteOptions - normalize vote options param string func NormalizeWeightedVoteOptions(options string) string { newOptions := []string{} for _, option := range strings.Split(options, ",") { From 188a8a2e15bbcc67c7c0c3951630030e5fdbd623 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Fri, 12 Feb 2021 12:26:24 -0500 Subject: [PATCH 128/152] import hygiene --- x/gov/types/vote.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x/gov/types/vote.go b/x/gov/types/vote.go index 72fa0bfbf338..da4317285c1f 100644 --- a/x/gov/types/vote.go +++ b/x/gov/types/vote.go @@ -5,8 +5,9 @@ import ( "fmt" "strings" - sdk "github.com/cosmos/cosmos-sdk/types" yaml "gopkg.in/yaml.v2" + + sdk "github.com/cosmos/cosmos-sdk/types" ) // NewVote creates a new Vote instance From a417b5142fd2ba124852095763a697fc7148c45d Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Fri, 12 Feb 2021 12:37:56 -0500 Subject: [PATCH 129/152] update CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 413fdef42801..aa9cb95669ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/{bank,distrib,gov,slashing,staking}) [\#8363](https://github.com/cosmos/cosmos-sdk/issues/8363) Store keys have been modified to allow for variable-length addresses. * (x/ibc) [\#8266](https://github.com/cosmos/cosmos-sdk/issues/8266) Add amino JSON for IBC messages in order to support Ledger text signing. * (x/evidence) [\#8502](https://github.com/cosmos/cosmos-sdk/pull/8502) `HandleEquivocationEvidence` persists the evidence to state. +* (x/gov) [\#7733](https://github.com/cosmos/cosmos-sdk/pull/7733) ADR 037 Implementation: Governance Split Votes ### Improvements @@ -73,7 +74,6 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements -* (x/gov) [\#7733](https://github.com/cosmos/cosmos-sdk/pull/7733) ADR 037 Implementation: Governance Split Votes * (x/bank) [\#8302](https://github.com/cosmos/cosmos-sdk/issues/8302) Add gRPC and CLI queries for client denomination metadata. * (tendermint) Bump Tendermint version to [v0.34.3](https://github.com/tendermint/tendermint/releases/tag/v0.34.3). From d9d078fbc25d322f4f8d58d1a9e03caf4dcb8a92 Mon Sep 17 00:00:00 2001 From: Marko Date: Mon, 15 Feb 2021 09:41:26 +0000 Subject: [PATCH 130/152] docs: rest_grpc updates (#8582) --- docs/core/grpc_rest.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/core/grpc_rest.md b/docs/core/grpc_rest.md index c78da2d94e48..ca59d3f14908 100644 --- a/docs/core/grpc_rest.md +++ b/docs/core/grpc_rest.md @@ -24,12 +24,12 @@ Cosmos SDK v0.40 introduced Protobuf as the main [encoding](./encoding) library, Each module exposes [`Msg` and `Query` Protobuf services](../building-modules/messages-and-queries.md) to define state transitions and state queries. These services are hooked up to gRPC via the following function inside the application: -https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc4/server/types/app.go#L39-L41 + The `grpc.Server` is a concrete gRPC server, which spawns and serves any gRPC requests. This server can be configured inside `~/.simapp/config/app.toml`: - `grpc.enable = true|false` field defines if the gRPC server should be enabled. Defaults to `true`. -- `grpc.address = {string}` field defines the address (really, the port, since the host should be kept at `0.0.0.0`) the server should bind to. Defaults to `0.0.0.0:9000`. +- `grpc.address = {string}` field defines the address (really, the port, since the host should be kept at `0.0.0.0`) the server should bind to. Defaults to `0.0.0.0:9090`. ::tip `~/.simapp` is the directory where the node's configuration and databases are stored. By default, it's set to `~/.{app_name}`. @@ -45,7 +45,7 @@ In Cosmos SDK v0.40, the node continues to serve a REST server. However, the exi All routes are configured under the following fields in `~/.simapp/config/app.toml`: -- `api.enable = true|false` field defines if the REST server should be enabled. Defaults to `true`. +- `api.enable = true|false` field defines if the REST server should be enabled. Defaults to `false`. - `api.address = {string}` field defines the address (really, the port, since the host should be kept at `0.0.0.0`) the server should bind to. Defaults to `tcp://0.0.0.0:1317`. - some additional API configuration options are defined in `~/.simapp/config/app.toml`, along with comments, please refer to that file directly. @@ -55,7 +55,7 @@ If, for various reasons, you cannot use gRPC (for example, you are building a we [gRPC-gateway](https://grpc-ecosystem.github.io/grpc-gateway/) is a tool to expose gRPC endpoints as REST endpoints. For each RPC endpoint defined in a Protobuf service, the SDK offers a REST equivalent. For instance, querying a balance could be done via the `/cosmos.bank.v1beta1.Query/AllBalances` gRPC endpoint, or alternatively via the gRPC-gateway `"/cosmos/bank/v1beta1/balances/{address}"` REST endpoint: both will return the same result. For each RPC method defined in a Protobuf service, the corresponding REST endpoint is defined as an option: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc4/proto/cosmos/bank/v1beta1/query.proto#L19-L22 ++++ For application developers, gRPC-gateway REST routes needs to be wired up to the REST server, this is done by calling the `RegisterGRPCGatewayRoutes` function on the ModuleManager. From e306e5b6f562bba2e4513cf74a51c842d8cf7c34 Mon Sep 17 00:00:00 2001 From: Amaury Date: Mon, 15 Feb 2021 11:01:44 +0100 Subject: [PATCH 131/152] Make gRPC requests go through tendermint Query (#8549) * Make gRPC requests go through tendermint Query * Remove commented code * Dry run in InitChain? * Save type of first run * Add metadata in repsonse * Factorize some code * Fix lint * Update comments * Fix md test * Fix test expected * Don't put RunGRPCQuery as clientCtx method * Update baseapp/grpcserver.go Co-authored-by: Robert Zaremba * Address review comments Co-authored-by: Robert Zaremba --- baseapp/grpcrouter.go | 34 ++++++++++++- baseapp/grpcserver.go | 83 ++++++++++++++++++-------------- client/grpc_query.go | 99 +++++++++++++++++++++----------------- server/grpc/server.go | 5 +- server/grpc/server_test.go | 8 ++- server/start.go | 2 +- server/types/app.go | 2 +- testutil/network/util.go | 2 +- 8 files changed, 142 insertions(+), 93 deletions(-) diff --git a/baseapp/grpcrouter.go b/baseapp/grpcrouter.go index de553589c975..95186f0b16da 100644 --- a/baseapp/grpcrouter.go +++ b/baseapp/grpcrouter.go @@ -2,6 +2,7 @@ package baseapp import ( "fmt" + "reflect" gogogrpc "github.com/gogo/protobuf/grpc" abci "github.com/tendermint/tendermint/abci/types" @@ -12,13 +13,19 @@ import ( "github.com/cosmos/cosmos-sdk/client/grpc/reflection" codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) var protoCodec = encoding.GetCodec(proto.Name) // GRPCQueryRouter routes ABCI Query requests to GRPC handlers type GRPCQueryRouter struct { - routes map[string]GRPCQueryHandler + routes map[string]GRPCQueryHandler + // returnTypes is a map of FQ method name => its return type. It is used + // for cache purposes: the first time a method handler is run, we save its + // return type in this map. Then, on subsequent method handler calls, we + // decode the ABCI response bytes using the cached return type. + returnTypes map[string]reflect.Type interfaceRegistry codectypes.InterfaceRegistry serviceData []serviceData } @@ -34,7 +41,8 @@ var _ gogogrpc.Server = &GRPCQueryRouter{} // NewGRPCQueryRouter creates a new GRPCQueryRouter func NewGRPCQueryRouter() *GRPCQueryRouter { return &GRPCQueryRouter{ - routes: map[string]GRPCQueryHandler{}, + returnTypes: map[string]reflect.Type{}, + routes: map[string]GRPCQueryHandler{}, } } @@ -89,8 +97,17 @@ func (qrt *GRPCQueryRouter) RegisterService(sd *grpc.ServiceDesc, handler interf if qrt.interfaceRegistry != nil { return codectypes.UnpackInterfaces(i, qrt.interfaceRegistry) } + return nil }, nil) + + // If it's the first time we call this handler, then we save + // the return type of the handler in the `returnTypes` map. + // The return type will be used for decoding subsequent requests. + if _, found := qrt.returnTypes[fqName]; !found { + qrt.returnTypes[fqName] = reflect.TypeOf(res) + } + if err != nil { return abci.ResponseQuery{}, err } @@ -127,3 +144,16 @@ func (qrt *GRPCQueryRouter) SetInterfaceRegistry(interfaceRegistry codectypes.In reflection.NewReflectionServiceServer(interfaceRegistry), ) } + +// returnTypeOf returns the return type of a gRPC method handler. With the way the +// `returnTypes` cache map is set up, the return type of a method handler is +// guaranteed to be found if it's retrieved **after** the method handler ran at +// least once. If not, then a logic error is return. +func (qrt *GRPCQueryRouter) returnTypeOf(method string) (reflect.Type, error) { + returnType, found := qrt.returnTypes[method] + if !found { + return nil, sdkerrors.Wrapf(sdkerrors.ErrLogic, "cannot find %s return type", method) + } + + return returnType, nil +} diff --git a/baseapp/grpcserver.go b/baseapp/grpcserver.go index a4342e0b8955..c1db08a555aa 100644 --- a/baseapp/grpcserver.go +++ b/baseapp/grpcserver.go @@ -2,67 +2,78 @@ package baseapp import ( "context" - "strconv" + "reflect" gogogrpc "github.com/gogo/protobuf/grpc" grpcmiddleware "github.com/grpc-ecosystem/go-grpc-middleware" grpcrecovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" "google.golang.org/grpc" - "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/client" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - grpctypes "github.com/cosmos/cosmos-sdk/types/grpc" + "github.com/cosmos/cosmos-sdk/types/tx" ) // GRPCQueryRouter returns the GRPCQueryRouter of a BaseApp. func (app *BaseApp) GRPCQueryRouter() *GRPCQueryRouter { return app.grpcQueryRouter } // RegisterGRPCServer registers gRPC services directly with the gRPC server. -func (app *BaseApp) RegisterGRPCServer(server gogogrpc.Server) { - // Define an interceptor for all gRPC queries: this interceptor will create - // a new sdk.Context, and pass it into the query handler. - interceptor := func(grpcCtx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { - // If there's some metadata in the context, retrieve it. - md, ok := metadata.FromIncomingContext(grpcCtx) - if !ok { - return nil, status.Error(codes.Internal, "unable to retrieve metadata") - } +func (app *BaseApp) RegisterGRPCServer(clientCtx client.Context, server gogogrpc.Server) { + // Define an interceptor for all gRPC queries: this interceptor will route + // the query through the `clientCtx`, which itself queries Tendermint. + interceptor := func(grpcCtx context.Context, req interface{}, info *grpc.UnaryServerInfo, _ grpc.UnaryHandler) (interface{}, error) { + // Two things can happen here: + // 1. either we're broadcasting a Tx, in which case we call Tendermint's broadcast endpoint directly, + // 2. or we are querying for state, in which case we call ABCI's Query. - // Get height header from the request context, if present. - var height int64 - if heightHeaders := md.Get(grpctypes.GRPCBlockHeightHeader); len(heightHeaders) > 0 { - height, err = strconv.ParseInt(heightHeaders[0], 10, 64) - if err != nil { - return nil, sdkerrors.Wrapf( - sdkerrors.ErrInvalidRequest, - "Baseapp.RegisterGRPCServer: invalid height header %q: %v", grpctypes.GRPCBlockHeightHeader, err) - } - if err := checkNegativeHeight(height); err != nil { - return nil, err + // Case 1. Broadcasting a Tx. + if reqProto, ok := req.(*tx.BroadcastTxRequest); ok { + if !ok { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "expected %T, got %T", (*tx.BroadcastTxRequest)(nil), req) } + + return client.TxServiceBroadcast(grpcCtx, clientCtx, reqProto) + } + + // Case 2. Querying state. + inMd, _ := metadata.FromIncomingContext(grpcCtx) + abciRes, outMd, err := client.RunGRPCQuery(clientCtx, grpcCtx, info.FullMethod, req, inMd) + if err != nil { + return nil, err } - // Create the sdk.Context. Passing false as 2nd arg, as we can't - // actually support proofs with gRPC right now. - sdkCtx, err := app.createQueryContext(height, false) + // We need to know the return type of the grpc method for + // unmarshalling abciRes.Value. + // + // When we call each method handler for the first time, we save its + // return type in the `returnTypes` map (see the method handler in + // `grpcrouter.go`). By this time, the method handler has already run + // at least once (in the RunGRPCQuery call), so we're sure the + // returnType maps is populated for this method. We're retrieving it + // for decoding. + returnType, err := app.GRPCQueryRouter().returnTypeOf(info.FullMethod) if err != nil { return nil, err } - // Attach the sdk.Context into the gRPC's context.Context. - grpcCtx = context.WithValue(grpcCtx, sdk.SdkContextKey, sdkCtx) + // returnType is a pointer to a struct. Here, we're creating res which + // is a new pointer to the underlying struct. + res := reflect.New(returnType.Elem()).Interface() - // Add relevant gRPC headers - if height == 0 { - height = sdkCtx.BlockHeight() // If height was not set in the request, set it to the latest + err = protoCodec.Unmarshal(abciRes.Value, res) + if err != nil { + return nil, err + } + + // Send the metadata header back. The metadata currently includes: + // - block height. + err = grpc.SendHeader(grpcCtx, outMd) + if err != nil { + return nil, err } - md = metadata.Pairs(grpctypes.GRPCBlockHeightHeader, strconv.FormatInt(height, 10)) - grpc.SetHeader(grpcCtx, md) - return handler(grpcCtx, req) + return res, nil } // Loop through all services and methods, add the interceptor, and register diff --git a/client/grpc_query.go b/client/grpc_query.go index fc8cdeeb80d5..011523944c54 100644 --- a/client/grpc_query.go +++ b/client/grpc_query.go @@ -24,51 +24,86 @@ var _ gogogrpc.ClientConn = Context{} var protoCodec = encoding.GetCodec(proto.Name) // Invoke implements the grpc ClientConn.Invoke method -func (ctx Context) Invoke(grpcCtx gocontext.Context, method string, args, reply interface{}, opts ...grpc.CallOption) (err error) { +func (ctx Context) Invoke(grpcCtx gocontext.Context, method string, req, reply interface{}, opts ...grpc.CallOption) (err error) { // Two things can happen here: // 1. either we're broadcasting a Tx, in which call we call Tendermint's broadcast endpoint directly, // 2. or we are querying for state, in which case we call ABCI's Query. - // In both cases, we don't allow empty request args (it will panic unexpectedly). - if reflect.ValueOf(args).IsNil() { + // In both cases, we don't allow empty request req (it will panic unexpectedly). + if reflect.ValueOf(req).IsNil() { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "request cannot be nil") } // Case 1. Broadcasting a Tx. - if isBroadcast(method) { - req, ok := args.(*tx.BroadcastTxRequest) + if reqProto, ok := req.(*tx.BroadcastTxRequest); ok { if !ok { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "expected %T, got %T", (*tx.BroadcastTxRequest)(nil), args) + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "expected %T, got %T", (*tx.BroadcastTxRequest)(nil), req) } - res, ok := reply.(*tx.BroadcastTxResponse) + resProto, ok := reply.(*tx.BroadcastTxResponse) if !ok { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "expected %T, got %T", (*tx.BroadcastTxResponse)(nil), args) + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "expected %T, got %T", (*tx.BroadcastTxResponse)(nil), req) } - broadcastRes, err := TxServiceBroadcast(grpcCtx, ctx, req) + broadcastRes, err := TxServiceBroadcast(grpcCtx, ctx, reqProto) if err != nil { return err } - *res = *broadcastRes + *resProto = *broadcastRes return err } // Case 2. Querying state. - reqBz, err := protoCodec.Marshal(args) + inMd, _ := metadata.FromOutgoingContext(grpcCtx) + abciRes, outMd, err := RunGRPCQuery(ctx, grpcCtx, method, req, inMd) if err != nil { return err } + err = protoCodec.Unmarshal(abciRes.Value, reply) + if err != nil { + return err + } + + for _, callOpt := range opts { + header, ok := callOpt.(grpc.HeaderCallOption) + if !ok { + continue + } + + *header.HeaderAddr = outMd + } + + if ctx.InterfaceRegistry != nil { + return types.UnpackInterfaces(reply, ctx.InterfaceRegistry) + } + + return nil +} + +// NewStream implements the grpc ClientConn.NewStream method +func (Context) NewStream(gocontext.Context, *grpc.StreamDesc, string, ...grpc.CallOption) (grpc.ClientStream, error) { + return nil, fmt.Errorf("streaming rpc not supported") +} + +// RunGRPCQuery runs a gRPC query from the clientCtx, given all necessary +// arguments for the gRPC method, and returns the ABCI response. It is used +// to factorize code between client (Invoke) and server (RegisterGRPCServer) +// gRPC handlers. +func RunGRPCQuery(ctx Context, grpcCtx gocontext.Context, method string, req interface{}, md metadata.MD) (abci.ResponseQuery, metadata.MD, error) { + reqBz, err := protoCodec.Marshal(req) + if err != nil { + return abci.ResponseQuery{}, nil, err + } + // parse height header - md, _ := metadata.FromOutgoingContext(grpcCtx) if heights := md.Get(grpctypes.GRPCBlockHeightHeader); len(heights) > 0 { height, err := strconv.ParseInt(heights[0], 10, 64) if err != nil { - return err + return abci.ResponseQuery{}, nil, err } if height < 0 { - return sdkerrors.Wrapf( + return abci.ResponseQuery{}, nil, sdkerrors.Wrapf( sdkerrors.ErrInvalidRequest, "client.Context.Invoke: height (%d) from %q must be >= 0", height, grpctypes.GRPCBlockHeightHeader) } @@ -76,19 +111,14 @@ func (ctx Context) Invoke(grpcCtx gocontext.Context, method string, args, reply ctx = ctx.WithHeight(height) } - req := abci.RequestQuery{ + abciReq := abci.RequestQuery{ Path: method, Data: reqBz, } - res, err := ctx.QueryABCI(req) + abciRes, err := ctx.QueryABCI(abciReq) if err != nil { - return err - } - - err = protoCodec.Unmarshal(res.Value, reply) - if err != nil { - return err + return abci.ResponseQuery{}, nil, err } // Create header metadata. For now the headers contain: @@ -96,28 +126,7 @@ func (ctx Context) Invoke(grpcCtx gocontext.Context, method string, args, reply // We then parse all the call options, if the call option is a // HeaderCallOption, then we manually set the value of that header to the // metadata. - md = metadata.Pairs(grpctypes.GRPCBlockHeightHeader, strconv.FormatInt(res.Height, 10)) - for _, callOpt := range opts { - header, ok := callOpt.(grpc.HeaderCallOption) - if !ok { - continue - } - - *header.HeaderAddr = md - } - - if ctx.InterfaceRegistry != nil { - return types.UnpackInterfaces(reply, ctx.InterfaceRegistry) - } - - return nil -} - -// NewStream implements the grpc ClientConn.NewStream method -func (Context) NewStream(gocontext.Context, *grpc.StreamDesc, string, ...grpc.CallOption) (grpc.ClientStream, error) { - return nil, fmt.Errorf("streaming rpc not supported") -} + md = metadata.Pairs(grpctypes.GRPCBlockHeightHeader, strconv.FormatInt(abciRes.Height, 10)) -func isBroadcast(method string) bool { - return method == "/cosmos.tx.v1beta1.Service/BroadcastTx" + return abciRes, md, nil } diff --git a/server/grpc/server.go b/server/grpc/server.go index f03c1d87b9fd..d9d0be1a032c 100644 --- a/server/grpc/server.go +++ b/server/grpc/server.go @@ -8,13 +8,14 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/reflection" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/server/types" ) // StartGRPCServer starts a gRPC server on the given address. -func StartGRPCServer(app types.Application, address string) (*grpc.Server, error) { +func StartGRPCServer(clientCtx client.Context, app types.Application, address string) (*grpc.Server, error) { grpcSrv := grpc.NewServer() - app.RegisterGRPCServer(grpcSrv) + app.RegisterGRPCServer(clientCtx, grpcSrv) // Reflection allows external clients to see what services and methods // the gRPC server exposes. diff --git a/server/grpc/server_test.go b/server/grpc/server_test.go index 846ce31a5968..5750b9e2e2b7 100644 --- a/server/grpc/server_test.go +++ b/server/grpc/server_test.go @@ -92,7 +92,7 @@ func (s *IntegrationTestSuite) TestGRPCServer_BankBalance() { grpc.Header(&header), ) blockHeight = header.Get(grpctypes.GRPCBlockHeightHeader) - s.Require().Equal([]string{"1"}, blockHeight) + s.Require().NotEmpty(blockHeight[0]) // blockHeight is []string, first element is block height. } func (s *IntegrationTestSuite) TestGRPCServer_Reflection() { @@ -124,8 +124,6 @@ func (s *IntegrationTestSuite) TestGRPCServer_GetTxsEvent() { Events: []string{"message.action=send"}, }, ) - // TODO Once https://github.com/cosmos/cosmos-sdk/pull/8029 is merged, this - // should not error anymore. s.Require().NoError(err) } @@ -185,9 +183,9 @@ func (s *IntegrationTestSuite) TestGRPCServerInvalidHeaderHeights() { value string wantErr string }{ - {"-1", "height < 0"}, + {"-1", "\"x-cosmos-block-height\" must be >= 0"}, {"9223372036854775808", "value out of range"}, // > max(int64) by 1 - {"-10", "height < 0"}, + {"-10", "\"x-cosmos-block-height\" must be >= 0"}, {"18446744073709551615", "value out of range"}, // max uint64, which is > max(int64) {"-9223372036854775809", "value out of range"}, // Out of the range of for negative int64 } diff --git a/server/start.go b/server/start.go index 764a67be52f4..eef353fa7ef8 100644 --- a/server/start.go +++ b/server/start.go @@ -318,7 +318,7 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App grpcWebSrv *http.Server ) if config.GRPC.Enable { - grpcSrv, err = servergrpc.StartGRPCServer(app, config.GRPC.Address) + grpcSrv, err = servergrpc.StartGRPCServer(clientCtx, app, config.GRPC.Address) if err != nil { return err } diff --git a/server/types/app.go b/server/types/app.go index bac708729488..ba702074b2a6 100644 --- a/server/types/app.go +++ b/server/types/app.go @@ -38,7 +38,7 @@ type ( // RegisterGRPCServer registers gRPC services directly with the gRPC // server. - RegisterGRPCServer(grpc.Server) + RegisterGRPCServer(client.Context, grpc.Server) // RegisterTxService registers the gRPC Query service for tx (such as tx // simulation, fetching txs by hash...). diff --git a/testutil/network/util.go b/testutil/network/util.go index 3a66039179ef..4f36d464018c 100644 --- a/testutil/network/util.go +++ b/testutil/network/util.go @@ -93,7 +93,7 @@ func startInProcess(cfg Config, val *Validator) error { } if val.AppConfig.GRPC.Enable { - grpcSrv, err := servergrpc.StartGRPCServer(app, val.AppConfig.GRPC.Address) + grpcSrv, err := servergrpc.StartGRPCServer(val.ClientCtx, app, val.AppConfig.GRPC.Address) if err != nil { return err } From d162b29cf4318217c8a802a2018150c5c89800bd Mon Sep 17 00:00:00 2001 From: MD Aleem <72057206+aleem1314@users.noreply.github.com> Date: Mon, 15 Feb 2021 16:11:39 +0530 Subject: [PATCH 132/152] Add pagination to GetValidatorSetByHeight response (#8567) * fix pagination * add test Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- client/grpc/tmservice/service.go | 4 + client/grpc/tmservice/service_test.go | 140 +++++++++++++++++++++----- client/rpc/validators.go | 8 ++ 3 files changed, 129 insertions(+), 23 deletions(-) diff --git a/client/grpc/tmservice/service.go b/client/grpc/tmservice/service.go index b621dff570c2..57668c0d7292 100644 --- a/client/grpc/tmservice/service.go +++ b/client/grpc/tmservice/service.go @@ -104,6 +104,9 @@ func (s queryServer) GetLatestValidatorSet(ctx context.Context, req *GetLatestVa outputValidatorsRes := &GetLatestValidatorSetResponse{ BlockHeight: validatorsRes.BlockHeight, Validators: make([]*Validator, len(validatorsRes.Validators)), + Pagination: &qtypes.PageResponse{ + Total: validatorsRes.Total, + }, } for i, validator := range validatorsRes.Validators { @@ -156,6 +159,7 @@ func (s queryServer) GetValidatorSetByHeight(ctx context.Context, req *GetValida outputValidatorsRes := &GetValidatorSetByHeightResponse{ BlockHeight: validatorsRes.BlockHeight, Validators: make([]*Validator, len(validatorsRes.Validators)), + Pagination: &qtypes.PageResponse{Total: validatorsRes.Total}, } for i, validator := range validatorsRes.Validators { diff --git a/client/grpc/tmservice/service_test.go b/client/grpc/tmservice/service_test.go index dd8f0dd50ee1..fb83ab9c2046 100644 --- a/client/grpc/tmservice/service_test.go +++ b/client/grpc/tmservice/service_test.go @@ -131,32 +131,126 @@ func (s IntegrationTestSuite) TestQueryLatestValidatorSet() { s.Require().Equal(validatorSetRes.Validators[0].PubKey, anyPub) } -func (s IntegrationTestSuite) TestQueryValidatorSetByHeight() { - val := s.network.Validators[0] - - // nil pagination - _, err := s.queryClient.GetValidatorSetByHeight(context.Background(), &tmservice.GetValidatorSetByHeightRequest{ - Height: 1, - Pagination: nil, - }) - s.Require().NoError(err) +func (s IntegrationTestSuite) TestLatestValidatorSet_GRPC() { + vals := s.network.Validators + testCases := []struct { + name string + req *tmservice.GetLatestValidatorSetRequest + expErr bool + expErrMsg string + }{ + {"nil request", nil, true, "cannot be nil"}, + {"no pagination", &tmservice.GetLatestValidatorSetRequest{}, false, ""}, + {"with pagination", &tmservice.GetLatestValidatorSetRequest{Pagination: &qtypes.PageRequest{Offset: 0, Limit: uint64(len(vals))}}, false, ""}, + } + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + grpcRes, err := s.queryClient.GetLatestValidatorSet(context.Background(), tc.req) + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.expErrMsg) + } else { + s.Require().NoError(err) + s.Require().Len(grpcRes.Validators, len(vals)) + s.Require().Equal(grpcRes.Pagination.Total, uint64(len(vals))) + content, ok := grpcRes.Validators[0].PubKey.GetCachedValue().(cryptotypes.PubKey) + s.Require().Equal(true, ok) + s.Require().Equal(content, vals[0].PubKey) + } + }) + } +} - _, err = s.queryClient.GetValidatorSetByHeight(context.Background(), &tmservice.GetValidatorSetByHeightRequest{ - Height: 1, - Pagination: &qtypes.PageRequest{ - Offset: 0, - Limit: 10, - }}) - s.Require().NoError(err) +func (s IntegrationTestSuite) TestLatestValidatorSet_GRPCGateway() { + vals := s.network.Validators + testCases := []struct { + name string + url string + expErr bool + expErrMsg string + }{ + {"no pagination", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/latest", vals[0].APIAddress), false, ""}, + {"pagination invalid fields", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/latest?pagination.offset=-1&pagination.limit=-2", vals[0].APIAddress), true, "strconv.ParseUint"}, + {"with pagination", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/latest?pagination.offset=0&pagination.limit=2", vals[0].APIAddress), false, ""}, + } + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + res, err := rest.GetRequest(tc.url) + s.Require().NoError(err) + if tc.expErr { + s.Require().Contains(string(res), tc.expErrMsg) + } else { + var result tmservice.GetLatestValidatorSetResponse + err = vals[0].ClientCtx.JSONMarshaler.UnmarshalJSON(res, &result) + s.Require().NoError(err) + s.Require().Equal(uint64(len(vals)), result.Pagination.Total) + anyPub, err := codectypes.NewAnyWithValue(vals[0].PubKey) + s.Require().NoError(err) + s.Require().Equal(result.Validators[0].PubKey, anyPub) + } + }) + } +} - // no pagination rest - _, err = rest.GetRequest(fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/%d", val.APIAddress, 1)) - s.Require().NoError(err) +func (s IntegrationTestSuite) TestValidatorSetByHeight_GRPC() { + vals := s.network.Validators + testCases := []struct { + name string + req *tmservice.GetValidatorSetByHeightRequest + expErr bool + expErrMsg string + }{ + {"nil request", nil, true, "request cannot be nil"}, + {"empty request", &tmservice.GetValidatorSetByHeightRequest{}, true, "height must be greater than 0"}, + {"no pagination", &tmservice.GetValidatorSetByHeightRequest{Height: 1}, false, ""}, + {"with pagination", &tmservice.GetValidatorSetByHeightRequest{Height: 1, Pagination: &qtypes.PageRequest{Offset: 0, Limit: 1}}, false, ""}, + } + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + grpcRes, err := s.queryClient.GetValidatorSetByHeight(context.Background(), tc.req) + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.expErrMsg) + } else { + s.Require().NoError(err) + s.Require().Len(grpcRes.Validators, len(vals)) + s.Require().Equal(grpcRes.Pagination.Total, uint64(len(vals))) + } + }) + } +} - // rest query with pagination - restRes, err := rest.GetRequest(fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/%d?pagination.offset=%d&pagination.limit=%d", val.APIAddress, 1, 0, 1)) - var validatorSetRes tmservice.GetValidatorSetByHeightResponse - s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(restRes, &validatorSetRes)) +func (s IntegrationTestSuite) TestValidatorSetByHeight_GRPCGateway() { + vals := s.network.Validators + testCases := []struct { + name string + url string + expErr bool + expErrMsg string + }{ + {"invalid height", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/%d", vals[0].APIAddress, -1), true, "height must be greater than 0"}, + {"no pagination", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/%d", vals[0].APIAddress, 1), false, ""}, + {"pagination invalid fields", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/%d?pagination.offset=-1&pagination.limit=-2", vals[0].APIAddress, 1), true, "strconv.ParseUint"}, + {"with pagination", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/%d?pagination.offset=0&pagination.limit=2", vals[0].APIAddress, 1), false, ""}, + } + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + res, err := rest.GetRequest(tc.url) + s.Require().NoError(err) + if tc.expErr { + s.Require().Contains(string(res), tc.expErrMsg) + } else { + var result tmservice.GetValidatorSetByHeightResponse + err = vals[0].ClientCtx.JSONMarshaler.UnmarshalJSON(res, &result) + s.Require().NoError(err) + s.Require().Equal(uint64(len(vals)), result.Pagination.Total) + } + }) + } } func TestIntegrationTestSuite(t *testing.T) { diff --git a/client/rpc/validators.go b/client/rpc/validators.go index 175e7ff91ee6..7760aead9935 100644 --- a/client/rpc/validators.go +++ b/client/rpc/validators.go @@ -79,12 +79,14 @@ type ValidatorOutput struct { type ResultValidatorsOutput struct { BlockHeight int64 `json:"block_height"` Validators []ValidatorOutput `json:"validators"` + Total uint64 `json:"total"` } func (rvo ResultValidatorsOutput) String() string { var b strings.Builder b.WriteString(fmt.Sprintf("block height: %d\n", rvo.BlockHeight)) + b.WriteString(fmt.Sprintf("total count: %d\n", rvo.Total)) for _, val := range rvo.Validators { b.WriteString( @@ -129,9 +131,15 @@ func GetValidators(ctx context.Context, clientCtx client.Context, height *int64, return ResultValidatorsOutput{}, err } + total := validatorsRes.Total + if validatorsRes.Total < 0 { + total = 0 + } + outputValidatorsRes := ResultValidatorsOutput{ BlockHeight: validatorsRes.BlockHeight, Validators: make([]ValidatorOutput, len(validatorsRes.Validators)), + Total: uint64(total), } for i := 0; i < len(validatorsRes.Validators); i++ { From a534a960dbfaf438dc86e93478033d9055cebebc Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Mon, 15 Feb 2021 02:53:10 -0800 Subject: [PATCH 133/152] types: use (*math/big.Int).BitLen() == 0 to check if value is 0 (#8580) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of using len((*math/big.Int).Bytes()) == 0, which expensively creates a byte slice and marshals a value, on the majority hot path, instead use the cheaper method .BitLen() to check if 0. Benchmarking results, just from types: name old time/op new time/op delta CoinsAdditionIntersect/sizes:_A_1,_B_1-8 132ns ± 2% 126ns ±13% -4.55% (p=0.050 n=10+10) CoinsAdditionIntersect/sizes:_A_5,_B_5-8 1.41µs ± 3% 1.41µs ± 2% ~ (p=1.000 n=10+10) CoinsAdditionIntersect/sizes:_A_5,_B_20-8 2.30µs ± 1% 2.27µs ± 3% ~ (p=0.066 n=10+10) CoinsAdditionIntersect/sizes:_A_1,_B_1000-8 30.9µs ± 3% 30.7µs ± 1% ~ (p=0.218 n=10+10) CoinsAdditionIntersect/sizes:_A_2,_B_1000-8 31.4µs ± 3% 30.8µs ± 2% -1.94% (p=0.015 n=10+10) CoinsAdditionNoIntersect/sizes:_A_1,_B_1-8 116ns ± 1% 114ns ± 4% ~ (p=0.142 n=10+10) CoinsAdditionNoIntersect/sizes:_A_5,_B_5-8 1.11µs ± 1% 1.08µs ± 3% -2.36% (p=0.003 n=8+10) CoinsAdditionNoIntersect/sizes:_A_5,_B_20-8 1.85µs ± 2% 1.82µs ± 1% -1.38% (p=0.001 n=10+9) CoinsAdditionNoIntersect/sizes:_A_1,_B_1000-8 30.7µs ± 1% 30.6µs ± 3% ~ (p=0.393 n=10+10) CoinsAdditionNoIntersect/sizes:_A_2,_B_1000-8 31.1µs ± 1% 30.7µs ± 2% -1.32% (p=0.015 n=10+10) CoinsAdditionNoIntersect/sizes:_A_1000,_B_2-8 31.0µs ± 2% 30.7µs ± 2% ~ (p=0.190 n=10+10) Bech32ifyPubKey-8 28.8µs ± 5% 28.8µs ± 3% ~ (p=0.965 n=10+8) GetPubKeyFromBech32-8 38.8µs ± 3% 39.4µs ± 2% +1.70% (p=0.013 n=9+10) ParseCoin-8 16.7µs ± 6% 15.8µs ± 4% -5.21% (p=0.001 n=10+10) MarshalTo-8 521ns ± 5% 508ns ± 3% -2.56% (p=0.029 n=10+10) UintMarshal-8 3.10µs ±17% 2.56µs ± 3% -17.45% (p=0.000 n=10+9) IntMarshal-8 2.52µs ±10% 1.94µs ± 2% -23.10% (p=0.000 n=10+10) name old alloc/op new alloc/op delta Bech32ifyPubKey-8 4.02kB ± 0% 4.02kB ± 0% ~ (all equal) GetPubKeyFromBech32-8 2.48kB ± 0% 2.48kB ± 0% ~ (all equal) ParseCoin-8 2.21kB ± 0% 2.21kB ± 0% ~ (all equal) MarshalTo-8 80.0B ± 0% 80.0B ± 0% ~ (all equal) UintMarshal-8 440B ± 0% 392B ± 0% -10.91% (p=0.000 n=10+10) IntMarshal-8 216B ± 0% 168B ± 0% -22.22% (p=0.000 n=10+10) name old allocs/op new allocs/op delta Bech32ifyPubKey-8 25.0 ± 0% 25.0 ± 0% ~ (all equal) GetPubKeyFromBech32-8 85.0 ± 0% 85.0 ± 0% ~ (all equal) ParseCoin-8 71.0 ± 0% 71.0 ± 0% ~ (all equal) MarshalTo-8 2.00 ± 0% 2.00 ± 0% ~ (all equal) UintMarshal-8 31.0 ± 0% 25.0 ± 0% -19.35% (p=0.000 n=10+10) IntMarshal-8 24.0 ± 0% 18.0 ± 0% -25.00% (p=0.000 n=10+10) name old speed new speed delta UintMarshal-8 2.27MB/s ±15% 2.75MB/s ± 2% +20.87% (p=0.000 n=10+8) IntMarshal-8 2.78MB/s ± 9% 3.60MB/s ± 2% +29.69% (p=0.000 n=10+10) Fixes #8575 Co-authored-by: Alessio Treglia Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- types/bench_test.go | 50 +++++++++++++++++++++++++++++++++++++++++++++ types/int.go | 2 +- types/int_test.go | 34 ++++++++++++++++++++++++++++++ types/uint.go | 2 +- types/uint_test.go | 34 ++++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+), 2 deletions(-) diff --git a/types/bench_test.go b/types/bench_test.go index 6c1cbc88cb09..e4d8a07e1ca0 100644 --- a/types/bench_test.go +++ b/types/bench_test.go @@ -28,3 +28,53 @@ func BenchmarkParseCoin(b *testing.B) { } } } + +func BenchmarkUintMarshal(b *testing.B) { + var values = []uint64{ + 0, + 1, + 1 << 10, + 1<<10 - 3, + 1<<63 - 1, + 1<<32 - 7, + 1<<22 - 8, + } + + var scratch [20]byte + b.ReportAllocs() + for i := 0; i < b.N; i++ { + for _, value := range values { + u := types.NewUint(value) + n, err := u.MarshalTo(scratch[:]) + if err != nil { + b.Fatal(err) + } + b.SetBytes(int64(n)) + } + } +} + +func BenchmarkIntMarshal(b *testing.B) { + var values = []int64{ + 0, + 1, + 1 << 10, + 1<<10 - 3, + 1<<63 - 1, + 1<<32 - 7, + 1<<22 - 8, + } + + var scratch [20]byte + b.ReportAllocs() + for i := 0; i < b.N; i++ { + for _, value := range values { + in := types.NewInt(value) + n, err := in.MarshalTo(scratch[:]) + if err != nil { + b.Fatal(err) + } + b.SetBytes(int64(n)) + } + } +} diff --git a/types/int.go b/types/int.go index 81f6b1c04ddb..c33ff040a51e 100644 --- a/types/int.go +++ b/types/int.go @@ -375,7 +375,7 @@ func (i *Int) MarshalTo(data []byte) (n int, err error) { if i.i == nil { i.i = new(big.Int) } - if len(i.i.Bytes()) == 0 { + if i.i.BitLen() == 0 { // The value 0 copy(data, []byte{0x30}) return 1, nil } diff --git a/types/int_test.go b/types/int_test.go index 4b26ddb8ada5..2992f938b384 100644 --- a/types/int_test.go +++ b/types/int_test.go @@ -1,6 +1,7 @@ package types_test import ( + "fmt" "math/big" "math/rand" "strconv" @@ -385,3 +386,36 @@ func (s *intTestSuite) TestIntEq() { _, resp, _, _, _ = sdk.IntEq(s.T(), sdk.OneInt(), sdk.ZeroInt()) s.Require().False(resp) } + +func TestRoundTripMarshalToInt(t *testing.T) { + var values = []int64{ + 0, + 1, + 1 << 10, + 1<<10 - 3, + 1<<63 - 1, + 1<<32 - 7, + 1<<22 - 8, + } + + for _, value := range values { + value := value + t.Run(fmt.Sprintf("%d", value), func(t *testing.T) { + t.Parallel() + + var scratch [20]byte + iv := sdk.NewInt(value) + n, err := iv.MarshalTo(scratch[:]) + if err != nil { + t.Fatal(err) + } + rt := new(sdk.Int) + if err := rt.Unmarshal(scratch[:n]); err != nil { + t.Fatal(err) + } + if !rt.Equal(iv) { + t.Fatalf("roundtrip=%q != original=%q", rt, iv) + } + }) + } +} diff --git a/types/uint.go b/types/uint.go index 2305d7386728..d449c5262b19 100644 --- a/types/uint.go +++ b/types/uint.go @@ -161,7 +161,7 @@ func (u *Uint) MarshalTo(data []byte) (n int, err error) { if u.i == nil { u.i = new(big.Int) } - if len(u.i.Bytes()) == 0 { + if u.i.BitLen() == 0 { // The value 0 copy(data, []byte{0x30}) return 1, nil } diff --git a/types/uint_test.go b/types/uint_test.go index 36705c890a19..b91f9ab4a96a 100644 --- a/types/uint_test.go +++ b/types/uint_test.go @@ -1,6 +1,7 @@ package types_test import ( + "fmt" "math" "math/big" "math/rand" @@ -290,3 +291,36 @@ func maxuint(i1, i2 uint64) uint64 { } return i2 } + +func TestRoundTripMarshalToUint(t *testing.T) { + var values = []uint64{ + 0, + 1, + 1 << 10, + 1<<10 - 3, + 1<<63 - 1, + 1<<32 - 7, + 1<<22 - 8, + } + + for _, value := range values { + value := value + t.Run(fmt.Sprintf("%d", value), func(t *testing.T) { + t.Parallel() + + var scratch [20]byte + uv := sdk.NewUint(value) + n, err := uv.MarshalTo(scratch[:]) + if err != nil { + t.Fatal(err) + } + rt := new(sdk.Uint) + if err := rt.Unmarshal(scratch[:n]); err != nil { + t.Fatal(err) + } + if !rt.Equal(uv) { + t.Fatalf("roundtrip=%q != original=%q", rt, uv) + } + }) + } +} From b4690d8ec6e2eba7354286d8533affd9ca687235 Mon Sep 17 00:00:00 2001 From: Marko Date: Mon, 15 Feb 2021 13:51:42 +0000 Subject: [PATCH 134/152] atlas: evidence (#8561) Co-authored-by: Aleksandr Bezobchuk --- .github/workflows/atlas.yml | 58 +++++++++++ x/evidence/atlas/atlas-v0.41.x.md | 167 ++++++++++++++++++++++++++++++ x/evidence/atlas/manifest.toml | 48 +++++++++ 3 files changed, 273 insertions(+) create mode 100644 .github/workflows/atlas.yml create mode 100644 x/evidence/atlas/atlas-v0.41.x.md create mode 100644 x/evidence/atlas/manifest.toml diff --git a/.github/workflows/atlas.yml b/.github/workflows/atlas.yml new file mode 100644 index 000000000000..25e749439dab --- /dev/null +++ b/.github/workflows/atlas.yml @@ -0,0 +1,58 @@ +name: Atlas +# Atlas checks if a modules atlas manifest has been touched, if so it publishes the updated version +on: + push: + branches: + - master + paths: + - "x/**/atlas/*" + pull_request: + paths: + - "x/**/atlas/*" + +jobs: + auth: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: technote-space/get-diff-action@v4 + id: git_diff + with: + PATTERNS: | + x/auth/atlas/** + - uses: marbar3778/atlas_action@main + with: + token: ${{ secrets.ATLAS_TOKEN }} + path: ./x/auth/atlas/atlas.toml + dry-run: ${{ github.event_name != 'pull_request' }} + if: env.GIT_DIFF + bank: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: technote-space/get-diff-action@v4 + id: git_diff + with: + PATTERNS: | + x/bank/atlas/** + - uses: marbar3778/atlas_action@main + with: + token: ${{ secrets.ATLAS_TOKEN }} + path: ./x/bank/atlas/atlas.toml + dry-run: ${{ github.event_name != 'pull_request' }} + if: env.GIT_DIFF + evidence: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: technote-space/get-diff-action@v4 + id: git_diff + with: + PATTERNS: | + x/evidence/atlas/** + - uses: marbar3778/atlas_action@main + with: + token: ${{ secrets.ATLAS_TOKEN }} + path: ./x/evidence/atlas/manifest.toml + dry-run: ${{ github.event_name != 'pull_request' }} + if: env.GIT_DIFF diff --git a/x/evidence/atlas/atlas-v0.41.x.md b/x/evidence/atlas/atlas-v0.41.x.md new file mode 100644 index 000000000000..e3df337513b8 --- /dev/null +++ b/x/evidence/atlas/atlas-v0.41.x.md @@ -0,0 +1,167 @@ +# x/evidence + +The `x/evidence` module is responsible for handling multi-asset coin transfers between +accounts and tracking special-case pseudo-transfers which must work differently +with particular kinds of accounts. + +## Usage + +1. Import the module. + + ```go + import ( + "github.com/cosmos/cosmos-sdk/x/evidence" + evidencekeeper "github.com/cosmos/cosmos-sdk/x/evidence/keeper" + evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" + ) + ``` + +2. Add `AppModuleBasic` to your `ModuleBasics`. + + ```go + var ( + ModuleBasics = module.NewBasicManager( + // ... + evidence.AppModuleBasic{}, + } + ) + ``` + +3. Add the evidence keeper to your apps struct. + + ```go + type app struct { + // ... + EvidenceKeeper evidencekeeper.Keeper + // ... + } + ``` + +4. Add the evidence store key to the group of store keys. + + ```go + func NewApp(...) *App { + // ... + keys := sdk.NewKVStoreKeys( + evidencetypes.StoreKey, + ) + // ... + } + ``` + +5. Create the keeper. Note, the `x/evidence` module depends on the `x/staking` and `x/slashing` modules. Evidence has expected interfaces, these interfaces are linked to slashing and staking. You can find these interfaces [here](https://github.com/cosmos/cosmos-sdk/blob/v0.41.0/x/evidence/types/expected_keepers.go) + + ```go + func NewApp(...) *App { + // ... + // create evidence keeper with router + evidenceKeeper := evidencekeeper.NewKeeper( + appCodec, keys[evidencetypes.StoreKey], &app.StakingKeeper, app.SlashingKeeper, + ) + } + ``` + +6. Add the `x/evidence` module to the app's `ModuleManager`. + + ```go + func NewApp(...) *App { + // ... + app.mm = module.NewManager( + // ... + evidence.NewAppModule(app.EvidenceKeeper), + // ... + ) + } + ``` + +7. Set the `x/evidence` module begin blocker order. + + ```go + func NewApp(...) *App { + // ... + app.mm.SetOrderBeginBlockers( + // ... + evidencetypes.ModuleName, + // ... + ) + } + ``` + +8. Set the `x/evidence` module genesis order. + + ```go + func NewApp(...) *App { + // ... + app.mm.SetOrderInitGenesis(..., evidencetypes.ModuleName, ...) + } + ``` + +9. Add the `x/evidence` module to the simulation manager (if you have one set). + + ```go + func NewApp(...) *App { + // ... + app.sm = module.NewSimulationManager( + // ... + evidence.NewAppModule(app.EvidenceKeeper), + // ... + ) + } + +## Genesis + +The `x/evidence` module defines its genesis state as follows: + +```proto +type GenesisState struct { + // evidence defines all the evidence at genesis. + Evidence []*types.Any `protobuf:"bytes,1,rep,name=evidence,proto3" json:"evidence,omitempty"` +} +``` + +## Messages + + +View supported messages at [docs.cosmos.network/v0.40/modules/evidence](https://docs.cosmos.network/v0.40/modules/evidence/03_messages.html) + +## Client + +Evidence supports querying of old evidence and submission of new evidence. There are two queries. One for all the evidence, and one for a specific piece of evidence. + +### CLI + +The evidence module supports the blow command to query evidence. + +```sh +Usage: + app query evidence [flags] + +Flags: + --count-total count total number of records in evidence to query for + --height int Use a specific height to query state at (this can error if the node is pruning state) + -h, --help help for evidence + --limit uint pagination limit of evidence to query for (default 100) + --node string : to Tendermint RPC interface for this chain (default "tcp://localhost:26657") + --offset uint pagination offset of evidence to query for + -o, --output string Output format (text|json) (default "text") + --page uint pagination page of evidence to query for. This sets offset to a multiple of limit (default 1) + --page-key string pagination page-key of evidence to query for +``` + +### REST + +Evidence REST API supports only queries of evidence. To submit evidence please use gRPC or the cli. + +### gRPC + +Evidence supports both querying and submitting transactions via gRPC + +#### Query + +[gRPC query](https://docs.cosmos.network/master/core/proto-docs.html#cosmos/evidence/v1beta1/query.proto) + +#### Tx + +[gRPC Tx](https://docs.cosmos.network/master/core/proto-docs.html#cosmos-evidence-v1beta1-tx-proto) + +View supported messages at [docs.cosmos.network/v0.40/modules/evidence](https://docs.cosmos.network/v0.40/modules/evidence/03_messages.html) diff --git a/x/evidence/atlas/manifest.toml b/x/evidence/atlas/manifest.toml new file mode 100644 index 000000000000..e277c6802445 --- /dev/null +++ b/x/evidence/atlas/manifest.toml @@ -0,0 +1,48 @@ +[module] +# Name of the module. (Required) +name = "x/evidence" + +# Description of the module. (Optional) +description = "The evidence module is responsible for storing and handling evidence of misbeaviour." + +# Link to where the module is located, it can also be a link to your project. (Optional) +homepage = "https://github.com/cosmos/cosmos-sdk" + +#List of key words describing your module (Optional) +keywords = [ + "evidence", + "misbeaviour", + "accountability" +] + + +[bug_tracker] +# A URL to a site that provides information or guidance on how to submit or deal +# with security vulnerabilities and bug reports. +url = "https://github.com/cosmos/cosmos-sdk/issues" + +# To list multiple authors, multiple [[authors]] need to be created +[[authors]] +# Name of one of the authors. Typically their Github name. (Required) +name = "alexanderbez" + +[[authors]] +name = "fedekunze" + +[[authors]] +name = "aaronc" + +[version] +# The repository field should be a URL to the source repository for your module. +# Typically, this will point to the specific GitHub repository release/tag for the +# module, although this is not enforced or required. (Required) +repo = "https://github.com/cosmos/cosmos-sdk" + +# The documentation field specifies a URL to a website hosting the module's documentation. (Optional) +documentation = "https://raw.githubusercontent.com/cosmos/cosmos-sdk/master/x/evidence/atlas/atlas-v0.41.x.md" + +# The module version to be published. (Required) +version = "v0.41" + +# An optional Cosmos SDK version compatibility may be provided. (Optional) +sdk_compat = "v0.41" From adbf5a71e6c62e787afc99694f226f3d3aa99480 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Mon, 15 Feb 2021 16:32:51 +0100 Subject: [PATCH 135/152] adr-028 address generation (#8415) * Optimize secp256k1 hashing * Add ADR-028 related functions * Update ed25519 * fix errors/handle * fix build * fix build * Add tests and update function names * wip * Use LengthPrefix for composed addresses * add tests for NewComposed * add module hash function * fix append * rollback ed25519 ADR-28 update * rollback ed25519 ADR-28 test * Adding Module tests and convert tests to test suite * convert store_key_test.go to test suite * rollback test check comment * Rename assert.Panic and add comment * add note to ed25519 about SDK support with regards to ADR-28 * Update ed25519 TestAddress * Adding Deprecated notes for ed25519.PrivKey * Update crypto/keys/ed25519/ed25519.go Co-authored-by: Marie Gauthier * Update types/address/hash_test.go Co-authored-by: Marie Gauthier * solve linter issues * linter: remove gocritic Co-authored-by: Marie Gauthier --- codec/amino.go | 4 +- crypto/codec/amino.go | 2 +- crypto/keyring/legacy.go | 2 +- crypto/keys/ed25519/ed25519.go | 8 ++- crypto/keys/ed25519/ed25519_test.go | 6 ++ crypto/keys/ed25519/keys.pb.go | 13 ++-- crypto/keys/secp256k1/secp256k1.go | 7 +- docs/core/proto-docs.md | 13 ++-- proto/cosmos/crypto/ed25519/keys.proto | 13 ++-- types/address/README.md | 7 ++ types/address/hash.go | 74 +++++++++++++++++++++ types/address/hash_test.go | 90 ++++++++++++++++++++++++++ types/address/store_key_test.go | 20 ++++-- types/errors/handle.go | 12 ++++ x/auth/types/account.go | 1 + x/staking/types/validator.go | 4 +- 16 files changed, 239 insertions(+), 37 deletions(-) create mode 100644 types/address/README.md create mode 100644 types/address/hash.go create mode 100644 types/address/hash_test.go create mode 100644 types/errors/handle.go diff --git a/codec/amino.go b/codec/amino.go index 78fd650ca4b8..ea4c8d4fd842 100644 --- a/codec/amino.go +++ b/codec/amino.go @@ -13,8 +13,8 @@ import ( "github.com/cosmos/cosmos-sdk/codec/types" ) -// deprecated: LegacyAmino defines a wrapper for an Amino codec that properly handles protobuf -// types with Any's +// LegacyAmino defines a wrapper for an Amino codec that properly +// handles protobuf types with Any's. Deprecated. type LegacyAmino struct { Amino *amino.Codec } diff --git a/crypto/codec/amino.go b/crypto/codec/amino.go index d50a08864c24..50119ed19858 100644 --- a/crypto/codec/amino.go +++ b/crypto/codec/amino.go @@ -26,7 +26,7 @@ func RegisterCrypto(cdc *codec.LegacyAmino) { cdc.RegisterInterface((*cryptotypes.PrivKey)(nil), nil) cdc.RegisterConcrete(sr25519.PrivKey{}, sr25519.PrivKeyName, nil) - cdc.RegisterConcrete(&ed25519.PrivKey{}, + cdc.RegisterConcrete(&ed25519.PrivKey{}, //nolint:staticcheck ed25519.PrivKeyName, nil) cdc.RegisterConcrete(&secp256k1.PrivKey{}, secp256k1.PrivKeyName, nil) diff --git a/crypto/keyring/legacy.go b/crypto/keyring/legacy.go index d6653e956159..94bff8232f42 100644 --- a/crypto/keyring/legacy.go +++ b/crypto/keyring/legacy.go @@ -42,7 +42,7 @@ var _ LegacyKeybase = dbKeybase{} // dbKeybase combines encryption and storage implementation to provide a // full-featured key manager. // -// NOTE: dbKeybase will be deprecated in favor of keyringKeybase. +// Deprecated: dbKeybase will be removed in favor of keyringKeybase. type dbKeybase struct { db dbm.DB } diff --git a/crypto/keys/ed25519/ed25519.go b/crypto/keys/ed25519/ed25519.go index 17368c4b12ff..7c70d573ec30 100644 --- a/crypto/keys/ed25519/ed25519.go +++ b/crypto/keys/ed25519/ed25519.go @@ -116,7 +116,8 @@ func (privKey *PrivKey) UnmarshalAminoJSON(bz []byte) error { return privKey.UnmarshalAmino(bz) } -// GenPrivKey generates a new ed25519 private key. +// GenPrivKey generates a new ed25519 private key. These ed25519 keys must not +// be used in SDK apps except in a tendermint validator context. // It uses OS randomness in conjunction with the current global random seed // in tendermint/libs/common to generate the private key. func GenPrivKey() *PrivKey { @@ -137,6 +138,7 @@ func genPrivKey(rand io.Reader) *PrivKey { // GenPrivKeyFromSecret hashes the secret with SHA2, and uses // that 32 byte output to create the private key. +// NOTE: ed25519 keys must not be used in SDK apps except in a tendermint validator context. // NOTE: secret should be the output of a KDF like bcrypt, // if it's derived from user input. func GenPrivKeyFromSecret(secret []byte) *PrivKey { @@ -151,10 +153,14 @@ var _ cryptotypes.PubKey = &PubKey{} var _ codec.AminoMarshaler = &PubKey{} // Address is the SHA256-20 of the raw pubkey bytes. +// It doesn't implement ADR-28 addresses and it must not be used +// in SDK except in a tendermint validator context. func (pubKey *PubKey) Address() crypto.Address { if len(pubKey.Key) != PubKeySize { panic("pubkey is incorrect size") } + // For ADR-28 compatible address we would need to + // return address.Hash(proto.MessageName(pubKey), pubKey.Key) return crypto.Address(tmhash.SumTruncated(pubKey.Key)) } diff --git a/crypto/keys/ed25519/ed25519_test.go b/crypto/keys/ed25519/ed25519_test.go index 59cce4066ac2..27cef37f92d6 100644 --- a/crypto/keys/ed25519/ed25519_test.go +++ b/crypto/keys/ed25519/ed25519_test.go @@ -84,6 +84,12 @@ func TestPubKeyEquals(t *testing.T) { } } +func TestAddressEd25519(t *testing.T) { + pk := ed25519.PubKey{[]byte{125, 80, 29, 208, 159, 53, 119, 198, 73, 53, 187, 33, 199, 144, 62, 255, 1, 235, 117, 96, 128, 211, 17, 45, 34, 64, 189, 165, 33, 182, 54, 206}} + addr := pk.Address() + require.Len(t, addr, 20, "Address must be 20 bytes long") +} + func TestPrivKeyEquals(t *testing.T) { ed25519PrivKey := ed25519.GenPrivKey() diff --git a/crypto/keys/ed25519/keys.pb.go b/crypto/keys/ed25519/keys.pb.go index 35a98cf05861..227b18701306 100644 --- a/crypto/keys/ed25519/keys.pb.go +++ b/crypto/keys/ed25519/keys.pb.go @@ -24,11 +24,11 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package -// PubKey defines a ed25519 public key -// Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte -// if the y-coordinate is the lexicographically largest of the two associated with -// the x-coordinate. Otherwise the first byte is a 0x03. -// This prefix is followed with the x-coordinate. +// PubKey is an ed25519 public key for handling Tendermint keys in SDK. +// It's needed for Any serialization and SDK compatibility. +// It must not be used in a non Tendermint key context because it doesn't implement +// ADR-28. Nevertheless, you will like to use ed25519 in app user level +// then you must create a new proto message and follow ADR-28 for Address construction. type PubKey struct { Key crypto_ed25519.PublicKey `protobuf:"bytes,1,opt,name=key,proto3,casttype=crypto/ed25519.PublicKey" json:"key,omitempty"` } @@ -72,7 +72,8 @@ func (m *PubKey) GetKey() crypto_ed25519.PublicKey { return nil } -// PrivKey defines a ed25519 private key. +// Deprecated: PrivKey defines a ed25519 private key. +// NOTE: ed25519 keys must not be used in SDK apps except in a tendermint validator context. type PrivKey struct { Key crypto_ed25519.PrivateKey `protobuf:"bytes,1,opt,name=key,proto3,casttype=crypto/ed25519.PrivateKey" json:"key,omitempty"` } diff --git a/crypto/keys/secp256k1/secp256k1.go b/crypto/keys/secp256k1/secp256k1.go index eebe72a45242..231a895a6103 100644 --- a/crypto/keys/secp256k1/secp256k1.go +++ b/crypto/keys/secp256k1/secp256k1.go @@ -151,12 +151,9 @@ func (pubKey *PubKey) Address() crypto.Address { panic("length of pubkey is incorrect") } - hasherSHA256 := sha256.New() - hasherSHA256.Write(pubKey.Key) // does not error - sha := hasherSHA256.Sum(nil) - + sha := sha256.Sum256(pubKey.Key) hasherRIPEMD160 := ripemd160.New() - hasherRIPEMD160.Write(sha) // does not error + hasherRIPEMD160.Write(sha[:]) // does not error return crypto.Address(hasherRIPEMD160.Sum(nil)) } diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index a0c6068d2539..c98035efc0b0 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -2885,7 +2885,8 @@ Msg defines the bank Msg service. ### PrivKey -PrivKey defines a ed25519 private key. +Deprecated: PrivKey defines a ed25519 private key. +NOTE: ed25519 keys must not be used in SDK apps except in a tendermint validator context. | Field | Type | Label | Description | @@ -2900,11 +2901,11 @@ PrivKey defines a ed25519 private key. ### PubKey -PubKey defines a ed25519 public key -Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte -if the y-coordinate is the lexicographically largest of the two associated with -the x-coordinate. Otherwise the first byte is a 0x03. -This prefix is followed with the x-coordinate. +PubKey is an ed25519 public key for handling Tendermint keys in SDK. +It's needed for Any serialization and SDK compatibility. +It must not be used in a non Tendermint key context because it doesn't implement +ADR-28. Nevertheless, you will like to use ed25519 in app user level +then you must create a new proto message and follow ADR-28 for Address construction. | Field | Type | Label | Description | diff --git a/proto/cosmos/crypto/ed25519/keys.proto b/proto/cosmos/crypto/ed25519/keys.proto index bed9c29cc797..6ffec3448370 100644 --- a/proto/cosmos/crypto/ed25519/keys.proto +++ b/proto/cosmos/crypto/ed25519/keys.proto @@ -5,18 +5,19 @@ import "gogoproto/gogo.proto"; option go_package = "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"; -// PubKey defines a ed25519 public key -// Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte -// if the y-coordinate is the lexicographically largest of the two associated with -// the x-coordinate. Otherwise the first byte is a 0x03. -// This prefix is followed with the x-coordinate. +// PubKey is an ed25519 public key for handling Tendermint keys in SDK. +// It's needed for Any serialization and SDK compatibility. +// It must not be used in a non Tendermint key context because it doesn't implement +// ADR-28. Nevertheless, you will like to use ed25519 in app user level +// then you must create a new proto message and follow ADR-28 for Address construction. message PubKey { option (gogoproto.goproto_stringer) = false; bytes key = 1 [(gogoproto.casttype) = "crypto/ed25519.PublicKey"]; } -// PrivKey defines a ed25519 private key. +// Deprecated: PrivKey defines a ed25519 private key. +// NOTE: ed25519 keys must not be used in SDK apps except in a tendermint validator context. message PrivKey { bytes key = 1 [(gogoproto.casttype) = "crypto/ed25519.PrivateKey"]; } diff --git a/types/address/README.md b/types/address/README.md new file mode 100644 index 000000000000..ebc647ec0f2b --- /dev/null +++ b/types/address/README.md @@ -0,0 +1,7 @@ +# Account + +This package defines Cosmos SDK address related functions. + +## References + ++ [ADR-028](../../docs/architecture/adr-028-public-key-addresses.md) diff --git a/types/address/hash.go b/types/address/hash.go new file mode 100644 index 000000000000..8c0cddae02e6 --- /dev/null +++ b/types/address/hash.go @@ -0,0 +1,74 @@ +package address + +import ( + "bytes" + "crypto/sha256" + "fmt" + "reflect" + "sort" + "unsafe" + + "github.com/cosmos/cosmos-sdk/types/errors" +) + +// Len is the length of base addresses +const Len = sha256.Size + +type Addressable interface { + Address() []byte +} + +// Hash creates a new address from address type and key +func Hash(typ string, key []byte) []byte { + hasher := sha256.New() + hasher.Write(unsafeStrToByteArray(typ)) + th := hasher.Sum(nil) + + hasher.Reset() + _, err := hasher.Write(th) + // the error always nil, it's here only to satisfy the io.Writer interface + errors.AssertNil(err) + _, err = hasher.Write(key) + errors.AssertNil(err) + return hasher.Sum(nil) +} + +// NewComposed creates a new address based on sub addresses. +func NewComposed(typ string, subAddresses []Addressable) ([]byte, error) { + as := make([][]byte, len(subAddresses)) + totalLen := 0 + var err error + for i := range subAddresses { + a := subAddresses[i].Address() + as[i], err = LengthPrefix(a) + if err != nil { + return nil, fmt.Errorf("not compatible sub-adddress=%v at index=%d [%w]", a, i, err) + } + totalLen += len(as[i]) + } + + sort.Slice(as, func(i, j int) bool { return bytes.Compare(as[i], as[j]) <= 0 }) + key := make([]byte, totalLen) + offset := 0 + for i := range as { + copy(key[offset:], as[i]) + offset += len(as[i]) + } + return Hash(typ, key), nil +} + +// Module is a specialized version of a composed address for modules. Each module account +// is constructed from a module name and module account key. +func Module(moduleName string, key []byte) []byte { + mKey := append([]byte(moduleName), 0) + return Hash("module", append(mKey, key...)) +} + +// unsafeStrToByteArray uses unsafe to convert string into byte array. Returned array +// cannot be altered after this functions is called +func unsafeStrToByteArray(s string) []byte { + sh := *(*reflect.SliceHeader)(unsafe.Pointer(&s)) + sh.Cap = sh.Len + bs := *(*[]byte)(unsafe.Pointer(&sh)) + return bs +} diff --git a/types/address/hash_test.go b/types/address/hash_test.go new file mode 100644 index 000000000000..be096c357fec --- /dev/null +++ b/types/address/hash_test.go @@ -0,0 +1,90 @@ +package address + +import ( + "crypto/sha256" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" +) + +func TestAddressSuite(t *testing.T) { + suite.Run(t, new(AddressSuite)) +} + +type AddressSuite struct{ suite.Suite } + +func (suite *AddressSuite) TestHash() { + assert := suite.Assert() + typ := "1" + key := []byte{1} + part1 := sha256.Sum256([]byte(typ)) + expected := sha256.Sum256(append(part1[:], key...)) + received := Hash(typ, key) + assert.Equal(expected[:], received, "must create a correct address") + + received = Hash("other", key) + assert.NotEqual(expected[:], received, "must create a correct address") + assert.Len(received, Len, "must have correct length") +} + +func (suite *AddressSuite) TestComposed() { + assert := suite.Assert() + a1 := addrMock{[]byte{11, 12}} + a2 := addrMock{[]byte{21, 22}} + + typ := "multisig" + ac, err := NewComposed(typ, []Addressable{a1, a2}) + assert.NoError(err) + assert.Len(ac, Len) + + // check if optimizations work + checkingKey := append([]byte{}, a1.AddressWithLen(suite.T())...) + checkingKey = append(checkingKey, a2.AddressWithLen(suite.T())...) + ac2 := Hash(typ, checkingKey) + assert.Equal(ac, ac2, "NewComposed works correctly") + + // changing order of addresses shouldn't impact a composed address + ac2, err = NewComposed(typ, []Addressable{a2, a1}) + assert.NoError(err) + assert.Len(ac2, Len) + assert.Equal(ac, ac2, "NewComposed is not sensitive for order") + + // changing a type should change composed address + ac2, err = NewComposed(typ+"other", []Addressable{a2, a1}) + assert.NoError(err) + assert.NotEqual(ac, ac2, "NewComposed must be sensitive to type") + + // changing order of addresses shouldn't impact a composed address + ac2, err = NewComposed(typ, []Addressable{a1, addrMock{make([]byte, 300, 300)}}) + assert.Error(err) + assert.Contains(err.Error(), "should be max 255 bytes, got 300") +} + +func (suite *AddressSuite) TestModule() { + assert := suite.Assert() + var modName, key = "myModule", []byte{1, 2} + addr := Module(modName, key) + assert.Len(addr, Len, "must have address length") + + addr2 := Module("myModule2", key) + assert.NotEqual(addr, addr2, "changing module name must change address") + + addr3 := Module(modName, []byte{1, 2, 3}) + assert.NotEqual(addr, addr3, "changing key must change address") + assert.NotEqual(addr2, addr3, "changing key must change address") +} + +type addrMock struct { + Addr []byte +} + +func (a addrMock) Address() []byte { + return a.Addr +} + +func (a addrMock) AddressWithLen(t *testing.T) []byte { + addr, err := LengthPrefix(a.Addr) + assert.NoError(t, err) + return addr +} diff --git a/types/address/store_key_test.go b/types/address/store_key_test.go index 3bb00bd022b0..ac28f814cc36 100644 --- a/types/address/store_key_test.go +++ b/types/address/store_key_test.go @@ -3,12 +3,19 @@ package address_test import ( "testing" - "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" "github.com/cosmos/cosmos-sdk/types/address" ) -func TestLengthPrefixedAddressStoreKey(t *testing.T) { +func TestStoreKeySuite(t *testing.T) { + suite.Run(t, new(StoreKeySuite)) +} + +type StoreKeySuite struct{ suite.Suite } + +func (suite *StoreKeySuite) TestLengthPrefix() { + require := suite.Require() addr10byte := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} addr20byte := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19} addr256byte := make([]byte, 256) @@ -23,15 +30,16 @@ func TestLengthPrefixedAddressStoreKey(t *testing.T) { {"20-byte address", addr20byte, append([]byte{byte(20)}, addr20byte...), false}, {"256-byte address (too long)", addr256byte, nil, true}, } + for _, tt := range tests { tt := tt - t.Run(tt.name, func(t *testing.T) { + suite.Run(tt.name, func() { storeKey, err := address.LengthPrefix(tt.addr) if tt.expErr { - require.Error(t, err) + require.Error(err) } else { - require.NoError(t, err) - require.Equal(t, tt.expStoreKey, storeKey) + require.NoError(err) + require.Equal(tt.expStoreKey, storeKey) } }) } diff --git a/types/errors/handle.go b/types/errors/handle.go new file mode 100644 index 000000000000..33c3fbfdeac2 --- /dev/null +++ b/types/errors/handle.go @@ -0,0 +1,12 @@ +package errors + +import "fmt" + +// AssertNil panics on error +// Should be only used with interface methods, which require return error, but the +// error is always nil +func AssertNil(err error) { + if err != nil { + panic(fmt.Errorf("logic error - this should never happen. %w", err)) + } +} diff --git a/x/auth/types/account.go b/x/auth/types/account.go index eb9939ffce10..653f89bcac4a 100644 --- a/x/auth/types/account.go +++ b/x/auth/types/account.go @@ -48,6 +48,7 @@ func ProtoBaseAccount() AccountI { } // NewBaseAccountWithAddress - returns a new base account with a given address +// leaving AccountNumber and Sequence to zero. func NewBaseAccountWithAddress(addr sdk.AccAddress) *BaseAccount { return &BaseAccount{ Address: addr.String(), diff --git a/x/staking/types/validator.go b/x/staking/types/validator.go index e551e752528c..b23a7708f094 100644 --- a/x/staking/types/validator.go +++ b/x/staking/types/validator.go @@ -103,9 +103,7 @@ func (v Validators) Less(i, j int) bool { // Implements sort interface func (v Validators) Swap(i, j int) { - it := v[i] - v[i] = v[j] - v[j] = it + v[i], v[j] = v[j], v[i] } // ValidatorsByVotingPower implements sort.Interface for []Validator based on From d3e51cf8a7474015926a67b76a67b9712d175e59 Mon Sep 17 00:00:00 2001 From: Prathyusha Lakkireddy Date: Mon, 15 Feb 2021 21:13:09 +0530 Subject: [PATCH 136/152] Improve create proposal code (#8586) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- x/gov/types/proposal.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/x/gov/types/proposal.go b/x/gov/types/proposal.go index 0c856647f64b..f9b59cbfc0a0 100644 --- a/x/gov/types/proposal.go +++ b/x/gov/types/proposal.go @@ -18,15 +18,6 @@ const DefaultStartingProposalID uint64 = 1 // NewProposal creates a new Proposal instance func NewProposal(content Content, id uint64, submitTime, depositEndTime time.Time) (Proposal, error) { - p := Proposal{ - ProposalId: id, - Status: StatusDepositPeriod, - FinalTallyResult: EmptyTallyResult(), - TotalDeposit: sdk.NewCoins(), - SubmitTime: submitTime, - DepositEndTime: depositEndTime, - } - msg, ok := content.(proto.Message) if !ok { return Proposal{}, fmt.Errorf("%T does not implement proto.Message", content) @@ -37,6 +28,15 @@ func NewProposal(content Content, id uint64, submitTime, depositEndTime time.Tim return Proposal{}, err } + p := Proposal{ + ProposalId: id, + Status: StatusDepositPeriod, + FinalTallyResult: EmptyTallyResult(), + TotalDeposit: sdk.NewCoins(), + SubmitTime: submitTime, + DepositEndTime: depositEndTime, + } + p.Content = any return p, nil From 47dd07d4ff227434a0ad7d5e1d12b6c1af07691a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Tue, 16 Feb 2021 16:31:40 +0100 Subject: [PATCH 137/152] Modify IBC client governance unfreezing to reflect ADR changes (#8405) * update proto files * make proto-gen * update clienttypes * update localhost and solo machine * refactor tm client proposal handling * copy metadata * self review fixes * update 02-client keeper tests * fix 02-client type tests * fix localhost and solomachine tests * begin updating tm tests * partially fix tm tests * increase codecov * add more tests * add changelog * update specs * add docs * fix test * modify adr * allow modified chain-ids * add CLI command * fix typos * fix lint * Apply suggestions from code review Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> * update docs, rm example * Update docs/ibc/proposals.md Co-authored-by: Christopher Goes * update height checks to reflect chain-id changes cc @AdityaSripal * Apply suggestions from code review Co-authored-by: Christopher Goes * Apply suggestions from code review Co-authored-by: Aditya * address most of @AdityaSripal suggestions * update docs per review suggestions * Update x/ibc/core/02-client/types/proposal.go * add proposal handler * register proposal type * register proposal on codec * fix routing Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Christopher Goes Co-authored-by: Aditya --- CHANGELOG.md | 1 + .../adr-026-ibc-client-recovery-mechanisms.md | 2 +- docs/core/proto-docs.md | 13 +- docs/ibc/README.md | 1 + docs/ibc/proposals.md | 42 ++ proto/ibc/core/client/v1/client.proto | 16 +- simapp/app.go | 3 +- x/ibc/core/02-client/client/cli/tx.go | 69 ++++ .../core/02-client/client/proposal_handler.go | 8 + x/ibc/core/02-client/keeper/proposal.go | 41 +- x/ibc/core/02-client/keeper/proposal_test.go | 99 +++-- x/ibc/core/02-client/proposal_handler_test.go | 26 +- x/ibc/core/02-client/types/client.pb.go | 175 +++++---- x/ibc/core/02-client/types/codec.go | 5 + x/ibc/core/02-client/types/errors.go | 2 + x/ibc/core/02-client/types/events.go | 1 + x/ibc/core/02-client/types/proposal.go | 50 ++- x/ibc/core/02-client/types/proposal_test.go | 67 ++-- x/ibc/core/exported/client.go | 2 +- x/ibc/core/spec/01_concepts.md | 28 +- x/ibc/core/spec/03_state_transitions.md | 5 +- .../06-solomachine/spec/01_concepts.md | 11 +- .../spec/03_state_transitions.md | 7 +- .../06-solomachine/types/proposal_handle.go | 55 ++- .../types/proposal_handle_test.go | 79 ++-- .../07-tendermint/types/proposal_handle.go | 165 ++++---- .../types/proposal_handle_test.go | 363 ++++++++++-------- .../07-tendermint/types/store.go | 7 + .../09-localhost/types/client_state.go | 11 +- .../09-localhost/types/client_state_test.go | 3 +- 30 files changed, 807 insertions(+), 550 deletions(-) create mode 100644 docs/ibc/proposals.md create mode 100644 x/ibc/core/02-client/client/proposal_handler.go diff --git a/CHANGELOG.md b/CHANGELOG.md index aa9cb95669ec..c39a1780e9aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/{bank,distrib,gov,slashing,staking}) [\#8363](https://github.com/cosmos/cosmos-sdk/issues/8363) Store keys have been modified to allow for variable-length addresses. * (x/ibc) [\#8266](https://github.com/cosmos/cosmos-sdk/issues/8266) Add amino JSON for IBC messages in order to support Ledger text signing. +* (x/ibc) [\#8405](https://github.com/cosmos/cosmos-sdk/pull/8405) Refactor IBC client update governance proposals to use a substitute client to update a frozen or expired client. * (x/evidence) [\#8502](https://github.com/cosmos/cosmos-sdk/pull/8502) `HandleEquivocationEvidence` persists the evidence to state. * (x/gov) [\#7733](https://github.com/cosmos/cosmos-sdk/pull/7733) ADR 037 Implementation: Governance Split Votes diff --git a/docs/architecture/adr-026-ibc-client-recovery-mechanisms.md b/docs/architecture/adr-026-ibc-client-recovery-mechanisms.md index 424f0415f60f..66eeaa13ea3f 100644 --- a/docs/architecture/adr-026-ibc-client-recovery-mechanisms.md +++ b/docs/architecture/adr-026-ibc-client-recovery-mechanisms.md @@ -44,7 +44,7 @@ We elect not to deal with chains which have actually halted, which is necessaril 1. Add a new governance proposal type, `ClientUpdateProposal`, in the `x/ibc` module 1. Extend the base `Proposal` with two client identifiers (`string`) and an initial height ('exported.Height'). 1. The first client identifier is the proposed client to be updated. This client must be either frozen or expired. - 1. The second client is a substitute client. It carries all the state for the client which may be updated. It must have identitical client and chain parameters to the client which may be updated (except for latest height and frozen height). It should be continually updated during the voting period. + 1. The second client is a substitute client. It carries all the state for the client which may be updated. It must have identitical client and chain parameters to the client which may be updated (except for latest height, frozen height, and chain-id). It should be continually updated during the voting period. 1. The initial height represents the starting height consensus states which will be copied from the substitute client to the frozen/expired client. 1. If this governance proposal passes, the client on trial will be updated with all the state of the substitute, if and only if: 1. `allow_governance_override_after_expiry` is true and the client has expired (`Expired()` returns true) diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index c98035efc0b0..2e39a4befc9a 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -7949,17 +7949,20 @@ client. ### ClientUpdateProposal -ClientUpdateProposal is a governance proposal. If it passes, the client is -updated with the provided header. The update may fail if the header is not -valid given certain conditions specified by the client implementation. +ClientUpdateProposal is a governance proposal. If it passes, the substitute client's +consensus states starting from the 'initial height' are copied over to the subjects +client state. The proposal handler may fail if the subject and the substitute do not +match in client and chain parameters (with exception to latest height, frozen height, and chain-id). +The updated client must also be valid (cannot be expired). | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `title` | [string](#string) | | the title of the update proposal | | `description` | [string](#string) | | the description of the proposal | -| `client_id` | [string](#string) | | the client identifier for the client to be updated if the proposal passes | -| `header` | [google.protobuf.Any](#google.protobuf.Any) | | the header used to update the client if the proposal passes | +| `subject_client_id` | [string](#string) | | the client identifier for the client to be updated if the proposal passes | +| `substitute_client_id` | [string](#string) | | the substitute client identifier for the client standing in for the subject client | +| `initial_height` | [Height](#ibc.core.client.v1.Height) | | the intital height to copy consensus states from the substitute to the subject | diff --git a/docs/ibc/README.md b/docs/ibc/README.md index 22061db94583..6298c119632b 100644 --- a/docs/ibc/README.md +++ b/docs/ibc/README.md @@ -12,6 +12,7 @@ This repository contains reference documentation for the IBC protocol integratio 2. [Integration](./integration.md) 3. [Customization](./custom.md) 4. [Relayer](./relayer.md) +5. [Governance Proposals](./proposals.md) After reading about IBC, head on to the [Building Modules documentation](../building-modules/README.md) to learn more about the process of building modules. diff --git a/docs/ibc/proposals.md b/docs/ibc/proposals.md new file mode 100644 index 000000000000..6bdf9f7051fc --- /dev/null +++ b/docs/ibc/proposals.md @@ -0,0 +1,42 @@ + + +# Governance Proposals + +In uncommon situations, a highly valued client may become frozen due to uncontrollable +circumstances. A highly valued client might have hundreds of channels being actively used. +Some of those channels might have a significant amount of locked tokens used for ICS 20. + +If the one third of the validator set of the chain the client represents decides to collude, +they can sign off on two valid but conflicting headers each signed by the other one third +of the honest validator set. The light client can now be updated with two valid, but conflicting +headers at the same height. The light client cannot know which header is trustworthy and therefore +evidence of such misbehaviour is likely to be submitted resulting in a frozen light client. + +Frozen light clients cannot be updated under any circumstance except via a governance proposal. +Since a quorum of validators can sign arbitrary state roots which may not be valid executions +of the state machine, a governance proposal has been added to ease the complexity of unfreezing +or updating clients which have become "stuck". Without this mechanism, validator sets would need +to construct a state root to unfreeze the client. Unfreezing clients, re-enables all of the channels +built upon that client. This may result in recovery of otherwise lost funds. + +Tendermint light clients may become expired if the trusting period has passed since their +last update. This may occur if relayers stop submitting headers to update the clients. + +An unplanned upgrade by the counterparty chain may also result in expired clients. If the counterparty +chain undergoes an unplanned upgrade, there may be no commitment to that upgrade signed by the validator +set before the chain-id changes. In this situation, the validator set of the last valid update for the +light client is never expected to produce another valid header since the chain-id has changed, which will +ultimately lead the on-chain light client to become expired. + +In the case that a highly valued light client is frozen, expired, or rendered non-updateable, a +governance proposal may be submitted to update this client, known as the subject client. The +proposal includes the client identifier for the subject, the client identifier for a substitute +client, and an initial height to reference the substitute client from. Light client implementations +may implement custom updating logic, but in most cases, the subject will be updated with information +from the substitute client, if the proposal passes. The substitute client is used as a "stand in" +while the subject is on trial. It is best practice to create a substitute client *after* the subject +has become frozen to avoid the substitute from also becoming frozen. An active substitute client +allows headers to be submitted during the voting period to prevent accidental expiry once the proposal +passes. diff --git a/proto/ibc/core/client/v1/client.proto b/proto/ibc/core/client/v1/client.proto index 11d2195aaf61..4c6308bd5415 100644 --- a/proto/ibc/core/client/v1/client.proto +++ b/proto/ibc/core/client/v1/client.proto @@ -33,9 +33,11 @@ message ClientConsensusStates { [(gogoproto.moretags) = "yaml:\"consensus_states\"", (gogoproto.nullable) = false]; } -// ClientUpdateProposal is a governance proposal. If it passes, the client is -// updated with the provided header. The update may fail if the header is not -// valid given certain conditions specified by the client implementation. +// ClientUpdateProposal is a governance proposal. If it passes, the substitute client's +// consensus states starting from the 'initial height' are copied over to the subjects +// client state. The proposal handler may fail if the subject and the substitute do not +// match in client and chain parameters (with exception to latest height, frozen height, and chain-id). +// The updated client must also be valid (cannot be expired). message ClientUpdateProposal { option (gogoproto.goproto_getters) = false; // the title of the update proposal @@ -43,9 +45,11 @@ message ClientUpdateProposal { // the description of the proposal string description = 2; // the client identifier for the client to be updated if the proposal passes - string client_id = 3 [(gogoproto.moretags) = "yaml:\"client_id\""]; - // the header used to update the client if the proposal passes - google.protobuf.Any header = 4; + string subject_client_id = 3 [(gogoproto.moretags) = "yaml:\"subject_client_id\""]; + // the substitute client identifier for the client standing in for the subject client + string substitute_client_id = 4 [(gogoproto.moretags) = "yaml:\"susbtitute_client_id\""]; + // the intital height to copy consensus states from the substitute to the subject + Height initial_height = 5 [(gogoproto.moretags) = "yaml:\"initial_height\"", (gogoproto.nullable) = false]; } // Height is a monotonically increasing data type diff --git a/simapp/app.go b/simapp/app.go index 4db7d53d7755..388c8c50eb8a 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -69,6 +69,7 @@ import ( ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" ibc "github.com/cosmos/cosmos-sdk/x/ibc/core" ibcclient "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client" + ibcclienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" porttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/05-port/types" ibchost "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" ibckeeper "github.com/cosmos/cosmos-sdk/x/ibc/core/keeper" @@ -309,7 +310,7 @@ func NewSimApp( AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)). AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)). AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)). - AddRoute(ibchost.RouterKey, ibcclient.NewClientUpdateProposalHandler(app.IBCKeeper.ClientKeeper)) + AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientUpdateProposalHandler(app.IBCKeeper.ClientKeeper)) app.GovKeeper = govkeeper.NewKeeper( appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper, &stakingKeeper, govRouter, diff --git a/x/ibc/core/02-client/client/cli/tx.go b/x/ibc/core/02-client/client/cli/tx.go index d036a5766d84..78313d21b7a3 100644 --- a/x/ibc/core/02-client/client/cli/tx.go +++ b/x/ibc/core/02-client/client/cli/tx.go @@ -11,7 +11,10 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" + govcli "github.com/cosmos/cosmos-sdk/x/gov/client/cli" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ) @@ -244,3 +247,69 @@ func NewUpgradeClientCmd() *cobra.Command { return cmd } + +// NewCmdSubmitUpdateClientProposal implements a command handler for submitting an update IBC client proposal transaction. +func NewCmdSubmitUpdateClientProposal() *cobra.Command { + cmd := &cobra.Command{ + Use: "update-client [subject-client-id] [substitute-client-id] [initial-height] [flags]", + Args: cobra.ExactArgs(3), + Short: "Submit an update IBC client proposal", + Long: "Submit an update IBC client proposal along with an initial deposit.\n" + + "Please specify a subject client identifier you want to update..\n" + + "Please specify the substitute client the subject client will use and the initial height to reference the substitute client's state.", + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + title, err := cmd.Flags().GetString(govcli.FlagTitle) + if err != nil { + return err + } + + description, err := cmd.Flags().GetString(govcli.FlagDescription) + if err != nil { + return err + } + + subjectClientID := args[0] + substituteClientID := args[1] + + initialHeight, err := types.ParseHeight(args[2]) + if err != nil { + return err + } + + content := types.NewClientUpdateProposal(title, description, subjectClientID, substituteClientID, initialHeight) + + from := clientCtx.GetFromAddress() + + depositStr, err := cmd.Flags().GetString(govcli.FlagDeposit) + if err != nil { + return err + } + deposit, err := sdk.ParseCoinsNormalized(depositStr) + if err != nil { + return err + } + + msg, err := govtypes.NewMsgSubmitProposal(content, deposit, from) + if err != nil { + return err + } + + if err = msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(govcli.FlagTitle, "", "title of proposal") + cmd.Flags().String(govcli.FlagDescription, "", "description of proposal") + cmd.Flags().String(govcli.FlagDeposit, "", "deposit of proposal") + + return cmd +} diff --git a/x/ibc/core/02-client/client/proposal_handler.go b/x/ibc/core/02-client/client/proposal_handler.go new file mode 100644 index 000000000000..63585cbe50b2 --- /dev/null +++ b/x/ibc/core/02-client/client/proposal_handler.go @@ -0,0 +1,8 @@ +package client + +import ( + govclient "github.com/cosmos/cosmos-sdk/x/gov/client" + "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/client/cli" +) + +var ProposalHandler = govclient.NewProposalHandler(cli.NewCmdSubmitUpdateClientProposal, nil) diff --git a/x/ibc/core/02-client/keeper/proposal.go b/x/ibc/core/02-client/keeper/proposal.go index 6b17278e09dd..6d4ff350df32 100644 --- a/x/ibc/core/02-client/keeper/proposal.go +++ b/x/ibc/core/02-client/keeper/proposal.go @@ -10,32 +10,41 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ) -// ClientUpdateProposal will try to update the client with the new header if and only if -// the proposal passes. The localhost client is not allowed to be modified with a proposal. +// ClientUpdateProposal will retrieve the subject and substitute client. +// The initial height must be greater than the latest height of the subject +// client. A callback will occur to the subject client state with the client +// prefixed store being provided for both the subject and the substitute client. +// The localhost client is not allowed to be modified with a proposal. The IBC +// client implementations are responsible for validating the parameters of the +// subtitute (enusring they match the subject's parameters) as well as copying +// the necessary consensus states from the subtitute to the subject client +// store. func (k Keeper) ClientUpdateProposal(ctx sdk.Context, p *types.ClientUpdateProposal) error { - if p.ClientId == exported.Localhost { + if p.SubjectClientId == exported.Localhost || p.SubstituteClientId == exported.Localhost { return sdkerrors.Wrap(types.ErrInvalidUpdateClientProposal, "cannot update localhost client with proposal") } - clientState, found := k.GetClientState(ctx, p.ClientId) + subjectClientState, found := k.GetClientState(ctx, p.SubjectClientId) if !found { - return sdkerrors.Wrapf(types.ErrClientNotFound, "cannot update client with ID %s", p.ClientId) + return sdkerrors.Wrapf(types.ErrClientNotFound, "subject client with ID %s", p.SubjectClientId) } - header, err := types.UnpackHeader(p.Header) - if err != nil { - return err + if subjectClientState.GetLatestHeight().GTE(p.InitialHeight) { + return sdkerrors.Wrapf(types.ErrInvalidHeight, "subject client state latest height is greater or equal to initial height (%s >= %s)", subjectClientState.GetLatestHeight(), p.InitialHeight) + } + + substituteClientState, found := k.GetClientState(ctx, p.SubstituteClientId) + if !found { + return sdkerrors.Wrapf(types.ErrClientNotFound, "substitute client with ID %s", p.SubstituteClientId) } - clientState, consensusState, err := clientState.CheckProposedHeaderAndUpdateState(ctx, k.cdc, k.ClientStore(ctx, p.ClientId), header) + clientState, err := subjectClientState.CheckSubstituteAndUpdateState(ctx, k.cdc, k.ClientStore(ctx, p.SubjectClientId), k.ClientStore(ctx, p.SubstituteClientId), substituteClientState, p.InitialHeight) if err != nil { return err } + k.SetClientState(ctx, p.SubjectClientId, clientState) - k.SetClientState(ctx, p.ClientId, clientState) - k.SetClientConsensusState(ctx, p.ClientId, header.GetHeight(), consensusState) - - k.Logger(ctx).Info("client updated after governance proposal passed", "client-id", p.ClientId, "height", clientState.GetLatestHeight().String()) + k.Logger(ctx).Info("client updated after governance proposal passed", "client-id", p.SubjectClientId, "height", clientState.GetLatestHeight().String()) defer func() { telemetry.IncrCounterWithLabels( @@ -43,7 +52,7 @@ func (k Keeper) ClientUpdateProposal(ctx sdk.Context, p *types.ClientUpdatePropo 1, []metrics.Label{ telemetry.NewLabel("client-type", clientState.ClientType()), - telemetry.NewLabel("client-id", p.ClientId), + telemetry.NewLabel("client-id", p.SubjectClientId), telemetry.NewLabel("update-type", "proposal"), }, ) @@ -53,9 +62,9 @@ func (k Keeper) ClientUpdateProposal(ctx sdk.Context, p *types.ClientUpdatePropo ctx.EventManager().EmitEvent( sdk.NewEvent( types.EventTypeUpdateClientProposal, - sdk.NewAttribute(types.AttributeKeyClientID, p.ClientId), + sdk.NewAttribute(types.AttributeKeySubjectClientID, p.SubjectClientId), sdk.NewAttribute(types.AttributeKeyClientType, clientState.ClientType()), - sdk.NewAttribute(types.AttributeKeyConsensusHeight, header.GetHeight().String()), + sdk.NewAttribute(types.AttributeKeyConsensusHeight, clientState.GetLatestHeight().String()), ), ) diff --git a/x/ibc/core/02-client/keeper/proposal_test.go b/x/ibc/core/02-client/keeper/proposal_test.go index ada205402b34..8dbe43f7d7f7 100644 --- a/x/ibc/core/02-client/keeper/proposal_test.go +++ b/x/ibc/core/02-client/keeper/proposal_test.go @@ -10,8 +10,11 @@ import ( func (suite *KeeperTestSuite) TestClientUpdateProposal() { var ( - content *types.ClientUpdateProposal - err error + subject, substitute string + subjectClientState, substituteClientState exported.ClientState + initialHeight clienttypes.Height + content *types.ClientUpdateProposal + err error ) testCases := []struct { @@ -21,53 +24,63 @@ func (suite *KeeperTestSuite) TestClientUpdateProposal() { }{ { "valid update client proposal", func() { - clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - clientState := suite.chainA.GetClientState(clientA) - - tmClientState, ok := clientState.(*ibctmtypes.ClientState) + content = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, initialHeight) + }, true, + }, + { + "subject and substitute use different revision numbers", func() { + tmClientState, ok := substituteClientState.(*ibctmtypes.ClientState) suite.Require().True(ok) - tmClientState.AllowUpdateAfterMisbehaviour = true - tmClientState.FrozenHeight = tmClientState.LatestHeight - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), clientA, tmClientState) + consState, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientConsensusState(suite.chainA.GetContext(), substitute, tmClientState.LatestHeight) + suite.Require().True(found) + newRevisionNumber := tmClientState.GetLatestHeight().GetRevisionNumber() + 1 - // use next header for chainB to update the client on chainA - header, err := suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, clientA) - suite.Require().NoError(err) + tmClientState.LatestHeight = clienttypes.NewHeight(newRevisionNumber, tmClientState.GetLatestHeight().GetRevisionHeight()) + initialHeight = clienttypes.NewHeight(newRevisionNumber, initialHeight.GetRevisionHeight()) + suite.chainA.App.IBCKeeper.ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), substitute, tmClientState.LatestHeight, consState) + suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), substitute, tmClientState) - content, err = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, clientA, header) - suite.Require().NoError(err) + content = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, initialHeight) }, true, }, { - "client type does not exist", func() { - content, err = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, ibctesting.InvalidID, &ibctmtypes.Header{}) - suite.Require().NoError(err) + "cannot use localhost as subject", func() { + content = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, exported.Localhost, substitute, initialHeight) }, false, }, { - "cannot update localhost", func() { - content, err = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, exported.Localhost, &ibctmtypes.Header{}) - suite.Require().NoError(err) + "cannot use localhost as substitute", func() { + content = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, exported.Localhost, initialHeight) }, false, }, { - "client does not exist", func() { - content, err = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, ibctesting.InvalidID, &ibctmtypes.Header{}) - suite.Require().NoError(err) + "subject client does not exist", func() { + content = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, ibctesting.InvalidID, substitute, initialHeight) }, false, }, { - "cannot unpack header, header is nil", func() { - clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - content = &clienttypes.ClientUpdateProposal{ibctesting.Title, ibctesting.Description, clientA, nil} + "substitute client does not exist", func() { + content = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, ibctesting.InvalidID, initialHeight) }, false, }, { - "update fails", func() { - header := &ibctmtypes.Header{} - clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - content, err = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, clientA, header) - suite.Require().NoError(err) + "subject and substitute have equal latest height", func() { + tmClientState, ok := subjectClientState.(*ibctmtypes.ClientState) + suite.Require().True(ok) + tmClientState.LatestHeight = substituteClientState.GetLatestHeight().(clienttypes.Height) + suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), subject, tmClientState) + + content = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, initialHeight) + }, false, + }, + { + "update fails, client is not frozen or expired", func() { + tmClientState, ok := subjectClientState.(*ibctmtypes.ClientState) + suite.Require().True(ok) + tmClientState.FrozenHeight = clienttypes.ZeroHeight() + suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), subject, tmClientState) + + content = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, initialHeight) }, false, }, } @@ -78,6 +91,30 @@ func (suite *KeeperTestSuite) TestClientUpdateProposal() { suite.Run(tc.name, func() { suite.SetupTest() // reset + subject, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + subjectClientState = suite.chainA.GetClientState(subject) + substitute, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + initialHeight = clienttypes.NewHeight(subjectClientState.GetLatestHeight().GetRevisionNumber(), subjectClientState.GetLatestHeight().GetRevisionHeight()+1) + + // update substitute twice + suite.coordinator.UpdateClient(suite.chainA, suite.chainB, substitute, exported.Tendermint) + suite.coordinator.UpdateClient(suite.chainA, suite.chainB, substitute, exported.Tendermint) + substituteClientState = suite.chainA.GetClientState(substitute) + + tmClientState, ok := subjectClientState.(*ibctmtypes.ClientState) + suite.Require().True(ok) + tmClientState.AllowUpdateAfterMisbehaviour = true + tmClientState.AllowUpdateAfterExpiry = true + tmClientState.FrozenHeight = tmClientState.LatestHeight + suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), subject, tmClientState) + + tmClientState, ok = substituteClientState.(*ibctmtypes.ClientState) + suite.Require().True(ok) + tmClientState.AllowUpdateAfterMisbehaviour = true + tmClientState.AllowUpdateAfterExpiry = true + tmClientState.FrozenHeight = tmClientState.LatestHeight + suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), substitute, tmClientState) + tc.malleate() err = suite.chainA.App.IBCKeeper.ClientKeeper.ClientUpdateProposal(suite.chainA.GetContext(), content) diff --git a/x/ibc/core/02-client/proposal_handler_test.go b/x/ibc/core/02-client/proposal_handler_test.go index 91c1451b7076..41b893186d65 100644 --- a/x/ibc/core/02-client/proposal_handler_test.go +++ b/x/ibc/core/02-client/proposal_handler_test.go @@ -24,21 +24,29 @@ func (suite *ClientTestSuite) TestNewClientUpdateProposalHandler() { }{ { "valid update client proposal", func() { - clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - clientState := suite.chainA.GetClientState(clientA) + subject, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + subjectClientState := suite.chainA.GetClientState(subject) + substitute, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + initialHeight := clienttypes.NewHeight(subjectClientState.GetLatestHeight().GetRevisionNumber(), subjectClientState.GetLatestHeight().GetRevisionHeight()+1) - tmClientState, ok := clientState.(*ibctmtypes.ClientState) + // update substitute twice + suite.coordinator.UpdateClient(suite.chainA, suite.chainB, substitute, exported.Tendermint) + suite.coordinator.UpdateClient(suite.chainA, suite.chainB, substitute, exported.Tendermint) + substituteClientState := suite.chainA.GetClientState(substitute) + + tmClientState, ok := subjectClientState.(*ibctmtypes.ClientState) suite.Require().True(ok) tmClientState.AllowUpdateAfterMisbehaviour = true tmClientState.FrozenHeight = tmClientState.LatestHeight - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), clientA, tmClientState) + suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), subject, tmClientState) - // use next header for chainB to update the client on chainA - header, err := suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, clientA) - suite.Require().NoError(err) + // replicate changes to substitute (they must match) + tmClientState, ok = substituteClientState.(*ibctmtypes.ClientState) + suite.Require().True(ok) + tmClientState.AllowUpdateAfterMisbehaviour = true + suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), substitute, tmClientState) - content, err = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, clientA, header) - suite.Require().NoError(err) + content = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, initialHeight) }, true, }, { diff --git a/x/ibc/core/02-client/types/client.pb.go b/x/ibc/core/02-client/types/client.pb.go index a42ddef4c593..61bdd9bf804d 100644 --- a/x/ibc/core/02-client/types/client.pb.go +++ b/x/ibc/core/02-client/types/client.pb.go @@ -191,18 +191,22 @@ func (m *ClientConsensusStates) GetConsensusStates() []ConsensusStateWithHeight return nil } -// ClientUpdateProposal is a governance proposal. If it passes, the client is -// updated with the provided header. The update may fail if the header is not -// valid given certain conditions specified by the client implementation. +// ClientUpdateProposal is a governance proposal. If it passes, the substitute client's +// consensus states starting from the 'initial height' are copied over to the subjects +// client state. The proposal handler may fail if the subject and the substitute do not +// match in client and chain parameters (with exception to latest height, frozen height, and chain-id). +// The updated client must also be valid (cannot be expired). type ClientUpdateProposal struct { // the title of the update proposal Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` // the description of the proposal Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` // the client identifier for the client to be updated if the proposal passes - ClientId string `protobuf:"bytes,3,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` - // the header used to update the client if the proposal passes - Header *types.Any `protobuf:"bytes,4,opt,name=header,proto3" json:"header,omitempty"` + SubjectClientId string `protobuf:"bytes,3,opt,name=subject_client_id,json=subjectClientId,proto3" json:"subject_client_id,omitempty" yaml:"subject_client_id"` + // the substitute client identifier for the client standing in for the subject client + SubstituteClientId string `protobuf:"bytes,4,opt,name=substitute_client_id,json=substituteClientId,proto3" json:"substitute_client_id,omitempty" yaml:"susbtitute_client_id"` + // the intital height to copy consensus states from the substitute to the subject + InitialHeight Height `protobuf:"bytes,5,opt,name=initial_height,json=initialHeight,proto3" json:"initial_height" yaml:"initial_height"` } func (m *ClientUpdateProposal) Reset() { *m = ClientUpdateProposal{} } @@ -344,43 +348,48 @@ func init() { func init() { proto.RegisterFile("ibc/core/client/v1/client.proto", fileDescriptor_b6bc4c8185546947) } var fileDescriptor_b6bc4c8185546947 = []byte{ - // 574 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0xbd, 0x8e, 0xd3, 0x4c, - 0x14, 0x8d, 0x93, 0x7c, 0xd1, 0x66, 0xf2, 0x29, 0x59, 0x99, 0x84, 0xf5, 0xa6, 0xb0, 0xa3, 0xa9, - 0x52, 0xec, 0xda, 0x24, 0x14, 0xa0, 0x74, 0x38, 0x0d, 0x5b, 0x80, 0x82, 0x11, 0x02, 0xd1, 0x44, - 0xfe, 0x99, 0x75, 0x46, 0x38, 0x9e, 0xc8, 0x33, 0x09, 0x9b, 0x37, 0xa0, 0xa4, 0xa4, 0xa0, 0xe0, - 0x09, 0xe8, 0x78, 0x03, 0x8a, 0x2d, 0xb7, 0xa4, 0xb2, 0x50, 0xf2, 0x06, 0x79, 0x02, 0xe4, 0x99, - 0xc9, 0x12, 0x07, 0x22, 0xad, 0xa8, 0x7c, 0x7d, 0xe6, 0xcc, 0xb9, 0xe7, 0xdc, 0x19, 0x0d, 0x30, - 0xb0, 0xe7, 0x5b, 0x3e, 0x49, 0x90, 0xe5, 0x47, 0x18, 0xc5, 0xcc, 0x5a, 0xf4, 0x64, 0x65, 0xce, - 0x12, 0xc2, 0x88, 0xaa, 0x62, 0xcf, 0x37, 0x33, 0x82, 0x29, 0xe1, 0x45, 0xaf, 0xdd, 0x0c, 0x49, - 0x48, 0xf8, 0xb2, 0x95, 0x55, 0x82, 0xd9, 0x3e, 0x0d, 0x09, 0x09, 0x23, 0x64, 0xf1, 0x3f, 0x6f, - 0x7e, 0x69, 0xb9, 0xf1, 0x52, 0x2c, 0xc1, 0xcf, 0x0a, 0x68, 0x5d, 0x04, 0x28, 0x66, 0xf8, 0x12, - 0xa3, 0x60, 0xc8, 0x85, 0x5e, 0x32, 0x97, 0x21, 0xb5, 0x07, 0xaa, 0x42, 0x77, 0x8c, 0x03, 0x4d, - 0xe9, 0x28, 0xdd, 0xaa, 0xdd, 0xdc, 0xa4, 0xc6, 0xf1, 0xd2, 0x9d, 0x46, 0x03, 0x78, 0xbb, 0x04, - 0x9d, 0x23, 0x51, 0x5f, 0x04, 0xea, 0x08, 0xfc, 0x2f, 0x71, 0x9a, 0x49, 0x68, 0xc5, 0x8e, 0xd2, - 0xad, 0xf5, 0x9b, 0xa6, 0x68, 0x6f, 0x6e, 0xdb, 0x9b, 0x4f, 0xe2, 0xa5, 0x7d, 0xb2, 0x49, 0x8d, - 0x7b, 0x39, 0x2d, 0xbe, 0x07, 0x3a, 0x35, 0xff, 0xb7, 0x09, 0xf8, 0x55, 0x01, 0xda, 0x90, 0xc4, - 0x14, 0xc5, 0x74, 0x4e, 0x39, 0xf4, 0x1a, 0xb3, 0xc9, 0x53, 0x84, 0xc3, 0x09, 0x53, 0x1f, 0x83, - 0xca, 0x84, 0x57, 0xdc, 0x5e, 0xad, 0xdf, 0x36, 0xff, 0x9c, 0x88, 0x29, 0xb8, 0x76, 0xf9, 0x3a, - 0x35, 0x0a, 0x8e, 0xe4, 0xab, 0x6f, 0x40, 0xc3, 0xdf, 0xaa, 0xde, 0xc1, 0xeb, 0xe9, 0x26, 0x35, - 0x5a, 0x99, 0x57, 0xb8, 0xb7, 0x0b, 0x3a, 0x75, 0x3f, 0xe7, 0x0e, 0x7e, 0x57, 0x40, 0x4b, 0x4c, - 0x31, 0x6f, 0x9b, 0xfe, 0xcb, 0x3c, 0xaf, 0xc0, 0xf1, 0x5e, 0x43, 0xaa, 0x15, 0x3b, 0xa5, 0x6e, - 0xad, 0x7f, 0xf6, 0xb7, 0xa8, 0x87, 0x06, 0x65, 0x1b, 0x59, 0xf8, 0x4d, 0x6a, 0x9c, 0xc8, 0x5e, - 0x7b, 0x9a, 0xd0, 0x69, 0xe4, 0x53, 0x50, 0xf8, 0x4d, 0x01, 0x4d, 0x11, 0xe3, 0xd5, 0x2c, 0x70, - 0x19, 0x1a, 0x25, 0x64, 0x46, 0xa8, 0x1b, 0xa9, 0x4d, 0xf0, 0x1f, 0xc3, 0x2c, 0x42, 0x22, 0x81, - 0x23, 0x7e, 0xd4, 0x0e, 0xa8, 0x05, 0x88, 0xfa, 0x09, 0x9e, 0x31, 0x4c, 0x62, 0x3e, 0xcb, 0xaa, - 0xb3, 0x0b, 0xe5, 0xd3, 0x97, 0xee, 0x94, 0xfe, 0x2c, 0x3b, 0x5e, 0x37, 0x40, 0x89, 0x56, 0x3e, - 0x7c, 0x36, 0x8e, 0xe4, 0x0c, 0xca, 0x1f, 0xbe, 0x18, 0x85, 0xec, 0x3a, 0x57, 0xe4, 0xed, 0x18, - 0x82, 0x46, 0x82, 0x16, 0x98, 0x62, 0x12, 0x8f, 0xe3, 0xf9, 0xd4, 0x43, 0x09, 0xf7, 0x5c, 0xb6, - 0xdb, 0x9b, 0xd4, 0xb8, 0x2f, 0xfa, 0xee, 0x11, 0xa0, 0x53, 0xdf, 0x22, 0xcf, 0x39, 0x90, 0x13, - 0x91, 0x77, 0xad, 0x78, 0x50, 0x44, 0x10, 0x76, 0x44, 0x84, 0x93, 0xc1, 0x51, 0x66, 0xed, 0x53, - 0x66, 0xef, 0x19, 0xa8, 0x8c, 0xdc, 0xc4, 0x9d, 0xd2, 0x4c, 0xd8, 0x8d, 0x22, 0xf2, 0x1e, 0x05, - 0x63, 0x11, 0x98, 0x6a, 0x4a, 0xa7, 0xd4, 0xad, 0xee, 0x0a, 0xef, 0x11, 0xa0, 0x53, 0x97, 0x88, - 0x38, 0x19, 0x6a, 0xbf, 0xb8, 0x5e, 0xe9, 0xca, 0xcd, 0x4a, 0x57, 0x7e, 0xae, 0x74, 0xe5, 0xe3, - 0x5a, 0x2f, 0xdc, 0xac, 0xf5, 0xc2, 0x8f, 0xb5, 0x5e, 0x78, 0xfb, 0x28, 0xc4, 0x6c, 0x32, 0xf7, - 0x4c, 0x9f, 0x4c, 0x2d, 0x9f, 0xd0, 0x29, 0xa1, 0xf2, 0x73, 0x4e, 0x83, 0x77, 0xd6, 0x95, 0x75, - 0xfb, 0xb6, 0x3c, 0xe8, 0x9f, 0xcb, 0xe7, 0x85, 0x2d, 0x67, 0x88, 0x7a, 0x15, 0x3e, 0xdc, 0x87, - 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0x39, 0xbe, 0xfd, 0x04, 0x7e, 0x04, 0x00, 0x00, + // 641 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0xbf, 0x6e, 0xd3, 0x40, + 0x1c, 0x8e, 0xd3, 0x34, 0x6a, 0x2e, 0x90, 0x14, 0x93, 0xd0, 0x34, 0x40, 0x2e, 0xba, 0x29, 0x03, + 0xb5, 0x69, 0x18, 0x40, 0xdd, 0x48, 0x96, 0x76, 0x00, 0xb5, 0x87, 0x10, 0x88, 0x25, 0xf8, 0xcf, + 0x35, 0x39, 0x70, 0x7c, 0x91, 0xef, 0x5c, 0x9a, 0x37, 0x60, 0x64, 0x64, 0x60, 0xe0, 0x09, 0x78, + 0x0a, 0x86, 0x8e, 0x95, 0x58, 0x98, 0x2c, 0xd4, 0xbe, 0x81, 0x9f, 0x00, 0xf9, 0xee, 0x92, 0x36, + 0x29, 0x15, 0x88, 0xc9, 0x3f, 0x7f, 0xf7, 0xfd, 0xbe, 0xdf, 0xf7, 0xfb, 0x74, 0x36, 0x80, 0xd4, + 0xf5, 0x6c, 0x8f, 0x45, 0xc4, 0xf6, 0x02, 0x4a, 0x42, 0x61, 0x1f, 0x6d, 0xeb, 0xca, 0x9a, 0x44, + 0x4c, 0x30, 0xd3, 0xa4, 0xae, 0x67, 0x65, 0x04, 0x4b, 0xc3, 0x47, 0xdb, 0xcd, 0xda, 0x90, 0x0d, + 0x99, 0x3c, 0xb6, 0xb3, 0x4a, 0x31, 0x9b, 0x9b, 0x43, 0xc6, 0x86, 0x01, 0xb1, 0xe5, 0x9b, 0x1b, + 0x1f, 0xda, 0x4e, 0x38, 0x55, 0x47, 0xe8, 0x8b, 0x01, 0xea, 0x7b, 0x3e, 0x09, 0x05, 0x3d, 0xa4, + 0xc4, 0xef, 0x4b, 0xa1, 0x17, 0xc2, 0x11, 0xc4, 0xdc, 0x06, 0x25, 0xa5, 0x3b, 0xa0, 0x7e, 0xc3, + 0x68, 0x1b, 0x9d, 0x52, 0xaf, 0x96, 0x26, 0x70, 0x7d, 0xea, 0x8c, 0x83, 0x1d, 0x34, 0x3f, 0x42, + 0x78, 0x4d, 0xd5, 0x7b, 0xbe, 0xb9, 0x0f, 0x6e, 0x68, 0x9c, 0x67, 0x12, 0x8d, 0x7c, 0xdb, 0xe8, + 0x94, 0xbb, 0x35, 0x4b, 0x8d, 0xb7, 0x66, 0xe3, 0xad, 0xa7, 0xe1, 0xb4, 0xb7, 0x91, 0x26, 0xf0, + 0xf6, 0x82, 0x96, 0xec, 0x41, 0xb8, 0xec, 0x5d, 0x98, 0x40, 0xdf, 0x0c, 0xd0, 0xe8, 0xb3, 0x90, + 0x93, 0x90, 0xc7, 0x5c, 0x42, 0xaf, 0xa8, 0x18, 0xed, 0x12, 0x3a, 0x1c, 0x09, 0xf3, 0x09, 0x28, + 0x8e, 0x64, 0x25, 0xed, 0x95, 0xbb, 0x4d, 0xeb, 0x6a, 0x22, 0x96, 0xe2, 0xf6, 0x0a, 0x27, 0x09, + 0xcc, 0x61, 0xcd, 0x37, 0x5f, 0x83, 0xaa, 0x37, 0x53, 0xfd, 0x07, 0xaf, 0x9b, 0x69, 0x02, 0xeb, + 0x99, 0x57, 0xb4, 0xd4, 0x85, 0x70, 0xc5, 0x5b, 0x70, 0x87, 0xbe, 0x1b, 0xa0, 0xae, 0x52, 0x5c, + 0xb4, 0xcd, 0xff, 0x27, 0xcf, 0x63, 0xb0, 0xbe, 0x34, 0x90, 0x37, 0xf2, 0xed, 0x95, 0x4e, 0xb9, + 0xfb, 0xe0, 0x4f, 0xab, 0x5e, 0x17, 0x54, 0x0f, 0x66, 0xcb, 0xa7, 0x09, 0xdc, 0xd0, 0xb3, 0x96, + 0x34, 0x11, 0xae, 0x2e, 0x6e, 0xc1, 0xd1, 0x8f, 0x3c, 0xa8, 0xa9, 0x35, 0x5e, 0x4e, 0x7c, 0x47, + 0x90, 0xfd, 0x88, 0x4d, 0x18, 0x77, 0x02, 0xb3, 0x06, 0x56, 0x05, 0x15, 0x01, 0x51, 0x1b, 0x60, + 0xf5, 0x62, 0xb6, 0x41, 0xd9, 0x27, 0xdc, 0x8b, 0xe8, 0x44, 0x50, 0x16, 0xca, 0x2c, 0x4b, 0xf8, + 0x32, 0x64, 0xee, 0x82, 0x5b, 0x3c, 0x76, 0xdf, 0x11, 0x4f, 0x0c, 0x2e, 0x52, 0x58, 0x91, 0x29, + 0xdc, 0x4b, 0x13, 0xd8, 0x50, 0xce, 0xae, 0x50, 0x10, 0xae, 0x6a, 0xac, 0x3f, 0x0b, 0xe5, 0x00, + 0xd4, 0x78, 0xec, 0x72, 0x41, 0x45, 0x2c, 0xc8, 0x25, 0xb1, 0x82, 0x14, 0x83, 0x69, 0x02, 0xef, + 0xce, 0xc4, 0xb8, 0xbb, 0xcc, 0x42, 0xd8, 0xbc, 0x68, 0x9e, 0x4b, 0xbe, 0x05, 0x15, 0x1a, 0x52, + 0x41, 0x9d, 0x60, 0xa0, 0x2f, 0xd4, 0xea, 0x5f, 0x2f, 0xd4, 0x7d, 0x9d, 0x69, 0x5d, 0x0d, 0x5b, + 0xec, 0x47, 0xf8, 0xa6, 0x06, 0x14, 0x7b, 0xa7, 0xf0, 0xf1, 0x2b, 0xcc, 0x65, 0x1f, 0x5b, 0x51, + 0xdf, 0xdd, 0x3e, 0xa8, 0x46, 0xe4, 0x88, 0x72, 0xca, 0xc2, 0x41, 0x18, 0x8f, 0x5d, 0x12, 0xc9, + 0x44, 0x0b, 0xbd, 0x66, 0x9a, 0xc0, 0x3b, 0x4a, 0x73, 0x89, 0x80, 0x70, 0x65, 0x86, 0x3c, 0x97, + 0xc0, 0x82, 0x88, 0x36, 0x9e, 0xbf, 0x56, 0x64, 0xe6, 0x6c, 0x2e, 0xa2, 0xad, 0xad, 0x65, 0xd6, + 0x3e, 0x67, 0xf6, 0x9e, 0x81, 0xe2, 0xbe, 0x13, 0x39, 0x63, 0x9e, 0x09, 0x3b, 0x41, 0xc0, 0x3e, + 0x10, 0x5f, 0x47, 0xc7, 0x1b, 0x46, 0x7b, 0xa5, 0x53, 0xba, 0x2c, 0xbc, 0x44, 0x40, 0xb8, 0xa2, + 0x11, 0x15, 0x2b, 0xef, 0x1d, 0x9c, 0x9c, 0xb5, 0x8c, 0xd3, 0xb3, 0x96, 0xf1, 0xeb, 0xac, 0x65, + 0x7c, 0x3a, 0x6f, 0xe5, 0x4e, 0xcf, 0x5b, 0xb9, 0x9f, 0xe7, 0xad, 0xdc, 0x9b, 0xc7, 0x43, 0x2a, + 0x46, 0xb1, 0x6b, 0x79, 0x6c, 0x6c, 0x7b, 0x8c, 0x8f, 0x19, 0xd7, 0x8f, 0x2d, 0xee, 0xbf, 0xb7, + 0x8f, 0xed, 0xf9, 0x9f, 0xef, 0x61, 0x77, 0x4b, 0xff, 0xfc, 0xc4, 0x74, 0x42, 0xb8, 0x5b, 0x94, + 0x9f, 0xe5, 0xa3, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x95, 0xe2, 0x8e, 0x47, 0x1c, 0x05, 0x00, + 0x00, } func (m *IdentifiedClientState) Marshal() (dAtA []byte, err error) { @@ -534,22 +543,27 @@ func (m *ClientUpdateProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.Header != nil { - { - size, err := m.Header.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintClient(dAtA, i, uint64(size)) + { + size, err := m.InitialHeight.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err } + i -= size + i = encodeVarintClient(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + if len(m.SubstituteClientId) > 0 { + i -= len(m.SubstituteClientId) + copy(dAtA[i:], m.SubstituteClientId) + i = encodeVarintClient(dAtA, i, uint64(len(m.SubstituteClientId))) i-- dAtA[i] = 0x22 } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintClient(dAtA, i, uint64(len(m.ClientId))) + if len(m.SubjectClientId) > 0 { + i -= len(m.SubjectClientId) + copy(dAtA[i:], m.SubjectClientId) + i = encodeVarintClient(dAtA, i, uint64(len(m.SubjectClientId))) i-- dAtA[i] = 0x1a } @@ -711,14 +725,16 @@ func (m *ClientUpdateProposal) Size() (n int) { if l > 0 { n += 1 + l + sovClient(uint64(l)) } - l = len(m.ClientId) + l = len(m.SubjectClientId) if l > 0 { n += 1 + l + sovClient(uint64(l)) } - if m.Header != nil { - l = m.Header.Size() + l = len(m.SubstituteClientId) + if l > 0 { n += 1 + l + sovClient(uint64(l)) } + l = m.InitialHeight.Size() + n += 1 + l + sovClient(uint64(l)) return n } @@ -1206,7 +1222,7 @@ func (m *ClientUpdateProposal) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field SubjectClientId", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1234,11 +1250,43 @@ func (m *ClientUpdateProposal) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ClientId = string(dAtA[iNdEx:postIndex]) + m.SubjectClientId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field SubstituteClientId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowClient + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthClient + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthClient + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SubstituteClientId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InitialHeight", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1265,10 +1313,7 @@ func (m *ClientUpdateProposal) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Header == nil { - m.Header = &types.Any{} - } - if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.InitialHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/x/ibc/core/02-client/types/codec.go b/x/ibc/core/02-client/types/codec.go index 8d79dcdaa45c..59a15832bec1 100644 --- a/x/ibc/core/02-client/types/codec.go +++ b/x/ibc/core/02-client/types/codec.go @@ -7,6 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/msgservice" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ) @@ -33,6 +34,10 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { "ibc.core.client.v1.Misbehaviour", (*exported.Misbehaviour)(nil), ) + registry.RegisterImplementations( + (*govtypes.Content)(nil), + &ClientUpdateProposal{}, + ) registry.RegisterImplementations( (*sdk.Msg)(nil), &MsgCreateClient{}, diff --git a/x/ibc/core/02-client/types/errors.go b/x/ibc/core/02-client/types/errors.go index 09dc92959a2b..5b44cd522211 100644 --- a/x/ibc/core/02-client/types/errors.go +++ b/x/ibc/core/02-client/types/errors.go @@ -30,4 +30,6 @@ var ( ErrUpdateClientFailed = sdkerrors.Register(SubModuleName, 23, "unable to update light client") ErrInvalidUpdateClientProposal = sdkerrors.Register(SubModuleName, 24, "invalid update client proposal") ErrInvalidUpgradeClient = sdkerrors.Register(SubModuleName, 25, "invalid client upgrade") + ErrInvalidHeight = sdkerrors.Register(SubModuleName, 26, "invalid height") + ErrInvalidSubstitute = sdkerrors.Register(SubModuleName, 27, "invalid client state substitute") ) diff --git a/x/ibc/core/02-client/types/events.go b/x/ibc/core/02-client/types/events.go index 779e87cee332..d0760ba89c8a 100644 --- a/x/ibc/core/02-client/types/events.go +++ b/x/ibc/core/02-client/types/events.go @@ -9,6 +9,7 @@ import ( // IBC client events const ( AttributeKeyClientID = "client_id" + AttributeKeySubjectClientID = "subject_client_id" AttributeKeyClientType = "client_type" AttributeKeyConsensusHeight = "consensus_height" ) diff --git a/x/ibc/core/02-client/types/proposal.go b/x/ibc/core/02-client/types/proposal.go index 334a9d4599ef..95b10aaf408e 100644 --- a/x/ibc/core/02-client/types/proposal.go +++ b/x/ibc/core/02-client/types/proposal.go @@ -1,10 +1,8 @@ package types import ( - codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ) const ( @@ -12,24 +10,21 @@ const ( ProposalTypeClientUpdate = "ClientUpdate" ) -var ( - _ govtypes.Content = &ClientUpdateProposal{} - _ codectypes.UnpackInterfacesMessage = ClientUpdateProposal{} -) +var _ govtypes.Content = &ClientUpdateProposal{} -// NewClientUpdateProposal creates a new client update proposal. -func NewClientUpdateProposal(title, description, clientID string, header exported.Header) (*ClientUpdateProposal, error) { - any, err := PackHeader(header) - if err != nil { - return nil, err - } +func init() { + govtypes.RegisterProposalType(ProposalTypeClientUpdate) +} +// NewClientUpdateProposal creates a new client update proposal. +func NewClientUpdateProposal(title, description, subjectClientID, substituteClientID string, initialHeight Height) *ClientUpdateProposal { return &ClientUpdateProposal{ - Title: title, - Description: description, - ClientId: clientID, - Header: any, - }, nil + Title: title, + Description: description, + SubjectClientId: subjectClientID, + SubstituteClientId: substituteClientID, + InitialHeight: initialHeight, + } } // GetTitle returns the title of a client update proposal. @@ -51,20 +46,19 @@ func (cup *ClientUpdateProposal) ValidateBasic() error { return err } - if err := host.ClientIdentifierValidator(cup.ClientId); err != nil { + if cup.SubjectClientId == cup.SubstituteClientId { + return sdkerrors.Wrap(ErrInvalidSubstitute, "subject and substitute client identifiers are equal") + } + if _, _, err := ParseClientIdentifier(cup.SubjectClientId); err != nil { return err } - - header, err := UnpackHeader(cup.Header) - if err != nil { + if _, _, err := ParseClientIdentifier(cup.SubstituteClientId); err != nil { return err } - return header.ValidateBasic() -} + if cup.InitialHeight.IsZero() { + return sdkerrors.Wrap(ErrInvalidHeight, "initial height cannot be zero height") + } -// UnpackInterfaces implements the UnpackInterfacesMessage interface. -func (cup ClientUpdateProposal) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - var header exported.Header - return unpacker.UnpackAny(cup.Header, &header) + return nil } diff --git a/x/ibc/core/02-client/types/proposal_test.go b/x/ibc/core/02-client/types/proposal_test.go index 5a47cf2f01cb..597e5cf8f801 100644 --- a/x/ibc/core/02-client/types/proposal_test.go +++ b/x/ibc/core/02-client/types/proposal_test.go @@ -5,35 +5,15 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" + "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" ) -func (suite *TypesTestSuite) TestNewUpdateClientProposal() { - p, err := types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, clientID, &ibctmtypes.Header{}) - suite.Require().NoError(err) - suite.Require().NotNil(p) - - p, err = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, clientID, nil) - suite.Require().Error(err) - suite.Require().Nil(p) -} - func (suite *TypesTestSuite) TestValidateBasic() { - // use solo machine header for testing - solomachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, clientID, "", 2) - smHeader := solomachine.CreateHeader() - header, err := types.PackHeader(smHeader) - suite.Require().NoError(err) - - // use a different pointer so we don't modify 'header' - smInvalidHeader := solomachine.CreateHeader() - - // a sequence of 0 will fail basic validation - smInvalidHeader.Sequence = 0 - - invalidHeader, err := types.PackHeader(smInvalidHeader) - suite.Require().NoError(err) + subject, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + subjectClientState := suite.chainA.GetClientState(subject) + substitute, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + initialHeight := types.NewHeight(subjectClientState.GetLatestHeight().GetRevisionNumber(), subjectClientState.GetLatestHeight().GetRevisionHeight()+1) testCases := []struct { name string @@ -42,22 +22,32 @@ func (suite *TypesTestSuite) TestValidateBasic() { }{ { "success", - &types.ClientUpdateProposal{ibctesting.Title, ibctesting.Description, clientID, header}, + types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, initialHeight), true, }, { "fails validate abstract - empty title", - &types.ClientUpdateProposal{"", ibctesting.Description, clientID, header}, + types.NewClientUpdateProposal("", ibctesting.Description, subject, substitute, initialHeight), + false, + }, + { + "subject and substitute use the same identifier", + types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, subject, initialHeight), + false, + }, + { + "invalid subject clientID", + types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, ibctesting.InvalidID, substitute, initialHeight), false, }, { - "fails to unpack header", - &types.ClientUpdateProposal{ibctesting.Title, ibctesting.Description, clientID, nil}, + "invalid substitute clientID", + types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, ibctesting.InvalidID, initialHeight), false, }, { - "fails header validate basic", - &types.ClientUpdateProposal{ibctesting.Title, ibctesting.Description, clientID, invalidHeader}, + "initial height is zero", + types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, types.ZeroHeight()), false, }, } @@ -74,22 +64,15 @@ func (suite *TypesTestSuite) TestValidateBasic() { } } -// tests a client update proposal can be marshaled and unmarshaled, and the -// client state can be unpacked +// tests a client update proposal can be marshaled and unmarshaled func (suite *TypesTestSuite) TestMarshalClientUpdateProposalProposal() { - _, err := types.PackHeader(&ibctmtypes.Header{}) - suite.Require().NoError(err) - // create proposal - header := suite.chainA.CurrentTMClientHeader() - proposal, err := types.NewClientUpdateProposal("update IBC client", "description", "client-id", header) - suite.Require().NoError(err) + proposal := types.NewClientUpdateProposal("update IBC client", "description", "subject", "substitute", types.NewHeight(1, 0)) // create codec ir := codectypes.NewInterfaceRegistry() types.RegisterInterfaces(ir) govtypes.RegisterInterfaces(ir) - ibctmtypes.RegisterInterfaces(ir) cdc := codec.NewProtoCodec(ir) // marshal message @@ -100,8 +83,4 @@ func (suite *TypesTestSuite) TestMarshalClientUpdateProposalProposal() { newProposal := &types.ClientUpdateProposal{} err = cdc.UnmarshalJSON(bz, newProposal) suite.Require().NoError(err) - - // unpack client state - _, err = types.UnpackHeader(newProposal.Header) - suite.Require().NoError(err) } diff --git a/x/ibc/core/exported/client.go b/x/ibc/core/exported/client.go index 656a233b3a9c..3d552b07724a 100644 --- a/x/ibc/core/exported/client.go +++ b/x/ibc/core/exported/client.go @@ -46,7 +46,7 @@ type ClientState interface { CheckHeaderAndUpdateState(sdk.Context, codec.BinaryMarshaler, sdk.KVStore, Header) (ClientState, ConsensusState, error) CheckMisbehaviourAndUpdateState(sdk.Context, codec.BinaryMarshaler, sdk.KVStore, Misbehaviour) (ClientState, error) - CheckProposedHeaderAndUpdateState(sdk.Context, codec.BinaryMarshaler, sdk.KVStore, Header) (ClientState, ConsensusState, error) + CheckSubstituteAndUpdateState(ctx sdk.Context, cdc codec.BinaryMarshaler, subjectClientStore, substituteClientStore sdk.KVStore, substituteClient ClientState, height Height) (ClientState, error) // Upgrade functions // NOTE: proof heights are not included as upgrade to a new revision is expected to pass only on the last diff --git a/x/ibc/core/spec/01_concepts.md b/x/ibc/core/spec/01_concepts.md index 045508999d39..4347fb674154 100644 --- a/x/ibc/core/spec/01_concepts.md +++ b/x/ibc/core/spec/01_concepts.md @@ -53,11 +53,11 @@ submission. ## ClientUpdateProposal -A governance proposal may be passed to update a specified client with a provided -header. This is useful in unfreezing clients or updating expired clients. Each -client is expected to implement this functionality. A client may choose to disallow -an update by a governance proposal by returning an error in the client state function -'CheckProposedHeaderAndUpdateState'. +A governance proposal may be passed to update a specified client using another client +known as the "substitute client". This is useful in unfreezing clients or updating +expired clients, thereby making the effected channels active again. Each client is +expected to implement this functionality. A client may choose to disallow an update +by a governance proposal by returning an error in the client state function 'CheckSubstituteAndUpdateState'. The localhost client cannot be updated by a governance proposal. @@ -68,9 +68,21 @@ be updated later. The tendermint client has two flags update flags, 'AllowUpdateAfterExpiry' and 'AllowUpdateAfterMisbehaviour'. The former flag can only be used to unexpire clients. The latter flag can be used to unfreeze a client and if necessary it will also unexpire the client. -It is advised to let a client expire if it has become frozen before proposing a new header. -This is to avoid the client from becoming refrozen if the misbehaviour evidence has not -expired. These boolean flags are set upon client creation and cannot be updated later. +It is best practice to initialize a new substitute client instead of using an existing one +This avoids potential issues of the substitute becoming frozen due to misbehaviour or the +subject client becoming refrozen due to misbehaviour not being expired at the time the +proposal passes. These boolean flags are set upon client creation and cannot be updated later. + +The `CheckSubstituteAndUpdateState` function provides the light client with its own client +store, the client store of the substitute, the substitute client state, and the intitial +height that should be used when referring to the substitute client. Most light client +implementations should copy consensus states from the substitute to the subject, but +are not required to do so. Light clients may copy informationa as they deem necessary. + +It is not recommended to use a substitute client in normal operations since the subject +light client will be given unrestricted access to the substitute client store. Governance +should not pass votes which enable byzantine light client modules from modifying the state +of the substitute. ## IBC Client Heights diff --git a/x/ibc/core/spec/03_state_transitions.md b/x/ibc/core/spec/03_state_transitions.md index be3b508b795c..518ff9247b97 100644 --- a/x/ibc/core/spec/03_state_transitions.md +++ b/x/ibc/core/spec/03_state_transitions.md @@ -27,8 +27,9 @@ parameters and if applicable will update to the new light client implementation. ## Client Update Proposal -An Update Client Proposal will unfreeze a client and set an updated `ClientState` and a new -`ConsensusState`. +An Update Client Proposal will unfreeze a client (if necessary) and set an updated `ClientState`. +The light client may make optional modifications to the client prefixed store of the subject client +including copying `ConsensusStates` from the substitute to the subject. ## Connection Open Init diff --git a/x/ibc/light-clients/06-solomachine/spec/01_concepts.md b/x/ibc/light-clients/06-solomachine/spec/01_concepts.md index fd8a4f71b20e..de486b71b1a8 100644 --- a/x/ibc/light-clients/06-solomachine/spec/01_concepts.md +++ b/x/ibc/light-clients/06-solomachine/spec/01_concepts.md @@ -129,17 +129,14 @@ If the update is successful: An update by a governance proposal will only succeed if: -- the header provided is parseable to solo machine header +- the substitute provided is parseable to solo machine client state - the `AllowUpdateAfterProposal` client parameter is set to `true` -- the new header public key does not equal the consensus state public key +- the new consensus state public key does not equal the current consensus state public key If the update is successful: -- the public key is updated -- the diversifier is updated -- the timestamp is updated -- the sequence is updated -- the new consensus state is set in the client state +- the subject client state is updated to the substitute client state +- the subject consensus state is updated to the substitute consensus state - the client is unfrozen (if it was previously frozen) ## Misbehaviour diff --git a/x/ibc/light-clients/06-solomachine/spec/03_state_transitions.md b/x/ibc/light-clients/06-solomachine/spec/03_state_transitions.md index 3ca4b7017acf..48a1e18f1c90 100644 --- a/x/ibc/light-clients/06-solomachine/spec/03_state_transitions.md +++ b/x/ibc/light-clients/06-solomachine/spec/03_state_transitions.md @@ -24,11 +24,8 @@ A successful update of a solo machine light client by a header will result in: A successful update of a solo machine light client by a governance proposal will result in: -- the public key being updated to the new public key provided by the header. -- the diversifier being updated to the new diviersifier provided by the header. -- the timestamp being updated to the new timestamp provided by the header. -- the sequence being set to the new sequence provided by the header. -- the consensus state being updated (consensus state stores the public key, diversifier, and timestamp) +- the client state being updated to the substitute client state +- the consensus state being updated to the substitute consensus state (consensus state stores the public key, diversifier, and timestamp) - the frozen sequence being set to zero (client is unfrozen if it was previously frozen). ## Upgrade diff --git a/x/ibc/light-clients/06-solomachine/types/proposal_handle.go b/x/ibc/light-clients/06-solomachine/types/proposal_handle.go index b55e612b3c96..e38155b23615 100644 --- a/x/ibc/light-clients/06-solomachine/types/proposal_handle.go +++ b/x/ibc/light-clients/06-solomachine/types/proposal_handle.go @@ -10,56 +10,55 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ) -// CheckProposedHeaderAndUpdateState updates the consensus state to the header's sequence and -// public key. An error is returned if the client has been disallowed to be updated by a -// governance proposal, the header cannot be casted to a solo machine header, or the current -// public key equals the new public key. -func (cs ClientState) CheckProposedHeaderAndUpdateState( - ctx sdk.Context, cdc codec.BinaryMarshaler, clientStore sdk.KVStore, - header exported.Header, -) (exported.ClientState, exported.ConsensusState, error) { +// CheckSubstituteAndUpdateState verifies that the subject is allowed to be updated by +// a governance proposal and that the substitute client is a solo machine. +// It will update the consensus state to the substitute's consensus state and +// the sequence to the substitute's current sequence. An error is returned if +// the client has been disallowed to be updated by a governance proposal, +// the substitute is not a solo machine, or the current public key equals +// the new public key. +func (cs ClientState) CheckSubstituteAndUpdateState( + ctx sdk.Context, cdc codec.BinaryMarshaler, subjectClientStore, + _ sdk.KVStore, substituteClient exported.ClientState, + _ exported.Height, +) (exported.ClientState, error) { if !cs.AllowUpdateAfterProposal { - return nil, nil, sdkerrors.Wrapf( + return nil, sdkerrors.Wrapf( clienttypes.ErrUpdateClientFailed, "solo machine client is not allowed to updated with a proposal", ) } - smHeader, ok := header.(*Header) + substituteClientState, ok := substituteClient.(*ClientState) if !ok { - return nil, nil, sdkerrors.Wrapf( - clienttypes.ErrInvalidHeader, "header type %T, expected %T", header, &Header{}, + return nil, sdkerrors.Wrapf( + clienttypes.ErrInvalidClientType, "substitute client state type %T, expected %T", substituteClient, &ClientState{}, ) } - consensusPublicKey, err := cs.ConsensusState.GetPubKey() + subjectPublicKey, err := cs.ConsensusState.GetPubKey() if err != nil { - return nil, nil, sdkerrors.Wrap(err, "failed to get consensus public key") + return nil, sdkerrors.Wrap(err, "failed to get consensus public key") } - headerPublicKey, err := smHeader.GetPubKey() + substitutePublicKey, err := substituteClientState.ConsensusState.GetPubKey() if err != nil { - return nil, nil, sdkerrors.Wrap(err, "failed to get header public key") + return nil, sdkerrors.Wrap(err, "failed to get substitute client public key") } - if reflect.DeepEqual(consensusPublicKey, headerPublicKey) { - return nil, nil, sdkerrors.Wrapf( - clienttypes.ErrInvalidHeader, "new public key in header equals current public key", + if reflect.DeepEqual(subjectPublicKey, substitutePublicKey) { + return nil, sdkerrors.Wrapf( + clienttypes.ErrInvalidHeader, "subject and substitute have the same public key", ) } clientState := &cs - consensusState := &ConsensusState{ - PublicKey: smHeader.NewPublicKey, - Diversifier: smHeader.NewDiversifier, - Timestamp: smHeader.Timestamp, - } - - clientState.Sequence = smHeader.Sequence - clientState.ConsensusState = consensusState + // update to substitute parameters + clientState.Sequence = substituteClientState.Sequence + clientState.ConsensusState = substituteClientState.ConsensusState clientState.FrozenSequence = 0 - return clientState, consensusState, nil + return clientState, nil } diff --git a/x/ibc/light-clients/06-solomachine/types/proposal_handle_test.go b/x/ibc/light-clients/06-solomachine/types/proposal_handle_test.go index da5c815ecbc8..0113da104497 100644 --- a/x/ibc/light-clients/06-solomachine/types/proposal_handle_test.go +++ b/x/ibc/light-clients/06-solomachine/types/proposal_handle_test.go @@ -7,8 +7,11 @@ import ( ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" ) -func (suite *SoloMachineTestSuite) TestCheckProposedHeaderAndUpdateState() { - var header exported.Header +func (suite *SoloMachineTestSuite) TestCheckSubstituteAndUpdateState() { + var ( + subjectClientState *types.ClientState + substituteClientState exported.ClientState + ) // test singlesig and multisig public keys for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { @@ -19,21 +22,34 @@ func (suite *SoloMachineTestSuite) TestCheckProposedHeaderAndUpdateState() { expPass bool }{ { - "valid header", func() { - header = solomachine.CreateHeader() + "valid substitute", func() { + subjectClientState.AllowUpdateAfterProposal = true }, true, }, { - "nil header", func() { - header = &ibctmtypes.Header{} + "subject not allowed to be updated", func() { + subjectClientState.AllowUpdateAfterProposal = false }, false, }, { - "header does not update public key", func() { - header = &types.Header{ - Sequence: 1, - NewPublicKey: solomachine.ConsensusState().PublicKey, - } + "substitute is not the solo machine", func() { + substituteClientState = &ibctmtypes.ClientState{} + }, false, + }, + { + "subject public key is nil", func() { + subjectClientState.ConsensusState.PublicKey = nil + }, false, + }, + + { + "substitute public key is nil", func() { + substituteClientState.(*types.ClientState).ConsensusState.PublicKey = nil + }, false, + }, + { + "subject and substitute use the same public key", func() { + substituteClientState.(*types.ClientState).ConsensusState.PublicKey = subjectClientState.ConsensusState.PublicKey }, false, }, } @@ -44,46 +60,27 @@ func (suite *SoloMachineTestSuite) TestCheckProposedHeaderAndUpdateState() { suite.Run(tc.name, func() { suite.SetupTest() - clientState := solomachine.ClientState() + subjectClientState = solomachine.ClientState() + subjectClientState.AllowUpdateAfterProposal = true + substitute := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "substitute", "testing", 5) + substituteClientState = substitute.ClientState() tc.malleate() - clientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), solomachine.ClientID) - - // all cases should always fail if the client has 'AllowUpdateAfterProposal' set to false - clientState.AllowUpdateAfterProposal = false - cs, consState, err := clientState.CheckProposedHeaderAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, header) - suite.Require().Error(err) - suite.Require().Nil(cs) - suite.Require().Nil(consState) + subjectClientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), solomachine.ClientID) + substituteClientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), substitute.ClientID) - clientState.AllowUpdateAfterProposal = true - cs, consState, err = clientState.CheckProposedHeaderAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, header) + updatedClient, err := subjectClientState.CheckSubstituteAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), subjectClientStore, substituteClientStore, substituteClientState, nil) if tc.expPass { suite.Require().NoError(err) - smConsState, ok := consState.(*types.ConsensusState) - suite.Require().True(ok) - smHeader, ok := header.(*types.Header) - suite.Require().True(ok) - - suite.Require().Equal(cs.(*types.ClientState).ConsensusState, consState) - - headerPubKey, err := smHeader.GetPubKey() - suite.Require().NoError(err) - - consStatePubKey, err := smConsState.GetPubKey() - suite.Require().NoError(err) - - suite.Require().Equal(headerPubKey, consStatePubKey) - suite.Require().Equal(smHeader.NewDiversifier, smConsState.Diversifier) - suite.Require().Equal(smHeader.Timestamp, smConsState.Timestamp) - suite.Require().Equal(smHeader.GetHeight().GetRevisionHeight(), cs.(*types.ClientState).Sequence) + suite.Require().Equal(substituteClientState.(*types.ClientState).ConsensusState, updatedClient.(*types.ClientState).ConsensusState) + suite.Require().Equal(substituteClientState.(*types.ClientState).Sequence, updatedClient.(*types.ClientState).Sequence) + suite.Require().Equal(uint64(0), updatedClient.(*types.ClientState).FrozenSequence) } else { suite.Require().Error(err) - suite.Require().Nil(cs) - suite.Require().Nil(consState) + suite.Require().Nil(updatedClient) } }) } diff --git a/x/ibc/light-clients/07-tendermint/types/proposal_handle.go b/x/ibc/light-clients/07-tendermint/types/proposal_handle.go index 4cd3eb376cbd..c64c52b3f810 100644 --- a/x/ibc/light-clients/07-tendermint/types/proposal_handle.go +++ b/x/ibc/light-clients/07-tendermint/types/proposal_handle.go @@ -1,9 +1,7 @@ package types import ( - "time" - - tmtypes "github.com/tendermint/tendermint/types" + "reflect" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" @@ -12,31 +10,52 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ) -// CheckProposedHeaderAndUpdateState will try to update the client with the new header if and -// only if the proposal passes and one of the following two conditions is satisfied: -// 1) AllowUpdateAfterExpiry=true and Expire(ctx.BlockTime) = true -// 2) AllowUpdateAfterMisbehaviour and IsFrozen() = true -// In case 2) before trying to update the client, the client will be unfrozen by resetting -// the FrozenHeight to the zero Height. If AllowUpdateAfterMisbehaviour is set to true, -// expired clients will also be updated even if AllowUpdateAfterExpiry is set to false. -// Note, that even if the update happens, it may not be successful. The header may fail -// validation checks and an error will be returned in that case. -func (cs ClientState) CheckProposedHeaderAndUpdateState( - ctx sdk.Context, cdc codec.BinaryMarshaler, clientStore sdk.KVStore, - header exported.Header, -) (exported.ClientState, exported.ConsensusState, error) { - tmHeader, ok := header.(*Header) +// CheckSubstituteAndUpdateState will try to update the client with the state of the +// substitute if and only if the proposal passes and one of the following conditions are +// satisfied: +// 1) AllowUpdateAfterMisbehaviour and IsFrozen() = true +// 2) AllowUpdateAfterExpiry=true and Expire(ctx.BlockTime) = true +// +// The following must always be true: +// - The substitute client is the same type as the subject client +// - The subject and substitute client states match in all parameters (expect frozen height, latest height, and chain-id) +// +// In case 1) before updating the client, the client will be unfrozen by resetting +// the FrozenHeight to the zero Height. If a client is frozen and AllowUpdateAfterMisbehaviour +// is set to true, the client will be unexpired even if AllowUpdateAfterExpiry is set to false. +// Note, that even if the subject is updated to the state of the substitute, an error may be +// returned if the updated client state is invalid or the client is expired. +func (cs ClientState) CheckSubstituteAndUpdateState( + ctx sdk.Context, cdc codec.BinaryMarshaler, subjectClientStore, + substituteClientStore sdk.KVStore, substituteClient exported.ClientState, + initialHeight exported.Height, +) (exported.ClientState, error) { + substituteClientState, ok := substituteClient.(*ClientState) if !ok { - return nil, nil, sdkerrors.Wrapf( - clienttypes.ErrInvalidHeader, "expected type %T, got %T", &Header{}, header, + return nil, sdkerrors.Wrapf( + clienttypes.ErrInvalidClient, "expected type %T, got %T", &ClientState{}, substituteClient, ) } + // substitute clients are not allowed to be upgraded during the voting period + // If an upgrade passes before the subject client has been updated, a new proposal must be created + // with an initial height that contains the new revision number. + if substituteClientState.GetLatestHeight().GetRevisionNumber() != initialHeight.GetRevisionNumber() { + return nil, sdkerrors.Wrapf( + clienttypes.ErrInvalidHeight, "substitute client revision number must equal initial height revision number (%d != %d)", + substituteClientState.GetLatestHeight().GetRevisionNumber(), initialHeight.GetRevisionNumber(), + ) + } + + if !IsMatchingClientState(cs, *substituteClientState) { + return nil, sdkerrors.Wrap(clienttypes.ErrInvalidSubstitute, "subject client state does not match substitute client state") + } + // get consensus state corresponding to client state to check if the client is expired - consensusState, err := GetConsensusState(clientStore, cdc, cs.GetLatestHeight()) + consensusState, err := GetConsensusState(subjectClientStore, cdc, cs.GetLatestHeight()) if err != nil { - return nil, nil, sdkerrors.Wrapf( - err, "could not get consensus state from clientstore at height: %d", cs.GetLatestHeight(), + return nil, sdkerrors.Wrapf( + err, "unexpected error: could not get consensus state from clientstore at height: %d", cs.GetLatestHeight(), ) } @@ -44,84 +63,72 @@ func (cs ClientState) CheckProposedHeaderAndUpdateState( case cs.IsFrozen(): if !cs.AllowUpdateAfterMisbehaviour { - return nil, nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "client is not allowed to be unfrozen") + return nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "client is not allowed to be unfrozen") } // unfreeze the client cs.FrozenHeight = clienttypes.ZeroHeight() - // if the client is expired we unexpire the client using softer validation, otherwise - // full validation on the header is performed. - if cs.IsExpired(consensusState.Timestamp, ctx.BlockTime()) { - return cs.unexpireClient(ctx, clientStore, consensusState, tmHeader, ctx.BlockTime()) + case cs.IsExpired(consensusState.Timestamp, ctx.BlockTime()): + if !cs.AllowUpdateAfterExpiry { + return nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "client is not allowed to be unexpired") } - // NOTE: the client may be frozen again since the misbehaviour evidence may - // not be expired yet - return cs.CheckHeaderAndUpdateState(ctx, cdc, clientStore, header) - - case cs.AllowUpdateAfterExpiry && cs.IsExpired(consensusState.Timestamp, ctx.BlockTime()): - return cs.unexpireClient(ctx, clientStore, consensusState, tmHeader, ctx.BlockTime()) - default: - return nil, nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "client cannot be updated with proposal") + return nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "client cannot be updated with proposal") } -} - -// unexpireClient checks if the proposed header is sufficient to update an expired client. -// The client is updated if no error occurs. -func (cs ClientState) unexpireClient( - ctx sdk.Context, clientStore sdk.KVStore, consensusState *ConsensusState, header *Header, currentTimestamp time.Time, -) (exported.ClientState, exported.ConsensusState, error) { + // copy consensus states and processed time from substitute to subject + // starting from initial height and ending on the latest height (inclusive) + for i := initialHeight.GetRevisionHeight(); i <= substituteClientState.GetLatestHeight().GetRevisionHeight(); i++ { + height := clienttypes.NewHeight(substituteClientState.GetLatestHeight().GetRevisionNumber(), i) - // the client is expired and either AllowUpdateAfterMisbehaviour or AllowUpdateAfterExpiry - // is set to true so light validation of the header is executed - if err := cs.checkProposedHeader(consensusState, header, currentTimestamp); err != nil { - return nil, nil, err - } + consensusState, err := GetConsensusState(substituteClientStore, cdc, height) + if err != nil { + // not all consensus states will be filled in + continue + } + SetConsensusState(subjectClientStore, cdc, consensusState, height) - newClientState, consensusState := update(ctx, clientStore, &cs, header) - return newClientState, consensusState, nil -} + processedTime, found := GetProcessedTime(substituteClientStore, height) + if !found { + continue + } + SetProcessedTime(subjectClientStore, height, processedTime) -// checkProposedHeader checks if the Tendermint header is valid for updating a client after -// a passed proposal. -// It returns an error if: -// - the header provided is not parseable to tendermint types -// - header height is less than or equal to the latest client state height -// - signed tendermint header is invalid -// - header timestamp is less than or equal to the latest consensus state timestamp -// - header timestamp is expired -// NOTE: header.ValidateBasic is called in the 02-client proposal handler. Additional checks -// on the validator set and the validator set hash are done in header.ValidateBasic. -func (cs ClientState) checkProposedHeader(consensusState *ConsensusState, header *Header, currentTimestamp time.Time) error { - tmSignedHeader, err := tmtypes.SignedHeaderFromProto(header.SignedHeader) - if err != nil { - return sdkerrors.Wrap(err, "signed header in not tendermint signed header type") } - if !header.GetTime().After(consensusState.Timestamp) { - return sdkerrors.Wrapf( - clienttypes.ErrInvalidHeader, - "header timestamp is less than or equal to latest consensus state timestamp (%s ≤ %s)", header.GetTime(), consensusState.Timestamp) + cs.LatestHeight = substituteClientState.LatestHeight + + // validate the updated client and ensure it isn't expired + if err := cs.Validate(); err != nil { + return nil, sdkerrors.Wrap(err, "unexpected error: updated subject client state is invalid") } - // assert header height is newer than latest client state - if header.GetHeight().LTE(cs.GetLatestHeight()) { - return sdkerrors.Wrapf( - clienttypes.ErrInvalidHeader, - "header height ≤ consensus state height (%s ≤ %s)", header.GetHeight(), cs.GetLatestHeight(), + latestConsensusState, err := GetConsensusState(subjectClientStore, cdc, cs.GetLatestHeight()) + if err != nil { + return nil, sdkerrors.Wrapf( + err, "unexpected error: could not get consensus state for updated subject client from clientstore at height: %d", cs.GetLatestHeight(), ) } - if err := tmSignedHeader.ValidateBasic(cs.GetChainID()); err != nil { - return sdkerrors.Wrap(err, "signed header failed basic validation") + if cs.IsExpired(latestConsensusState.Timestamp, ctx.BlockTime()) { + return nil, sdkerrors.Wrap(clienttypes.ErrInvalidClient, "updated subject client is expired") } - if cs.IsExpired(header.GetTime(), currentTimestamp) { - return sdkerrors.Wrap(clienttypes.ErrInvalidHeader, "header timestamp is already expired") - } + return &cs, nil +} - return nil +// IsMatchingClientState returns true if all the client state parameters match +// except for frozen height, latest height, and chain-id. +func IsMatchingClientState(subject, substitute ClientState) bool { + // zero out parameters which do not need to match + subject.LatestHeight = clienttypes.ZeroHeight() + subject.FrozenHeight = clienttypes.ZeroHeight() + substitute.LatestHeight = clienttypes.ZeroHeight() + substitute.FrozenHeight = clienttypes.ZeroHeight() + subject.ChainId = "" + substitute.ChainId = "" + + return reflect.DeepEqual(subject, substitute) } diff --git a/x/ibc/light-clients/07-tendermint/types/proposal_handle_test.go b/x/ibc/light-clients/07-tendermint/types/proposal_handle_test.go index 6863ad1d1c80..c1fb05413d9d 100644 --- a/x/ibc/light-clients/07-tendermint/types/proposal_handle_test.go +++ b/x/ibc/light-clients/07-tendermint/types/proposal_handle_test.go @@ -1,6 +1,8 @@ package types_test import ( + "time" + clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" @@ -11,38 +13,120 @@ var ( frozenHeight = clienttypes.NewHeight(0, 1) ) -// sanity checks -func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateStateBasic() { - clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - clientState := suite.chainA.GetClientState(clientA).(*types.ClientState) - clientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA) - - // use nil header - cs, consState, err := clientState.CheckProposedHeaderAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, nil) - suite.Require().Error(err) - suite.Require().Nil(cs) - suite.Require().Nil(consState) - - clientState.LatestHeight = clientState.LatestHeight.Increment().(clienttypes.Height) - - // consensus state for latest height does not exist - cs, consState, err = clientState.CheckProposedHeaderAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, suite.chainA.LastHeader) - suite.Require().Error(err) - suite.Require().Nil(cs) - suite.Require().Nil(consState) +func (suite *TendermintTestSuite) TestCheckSubstituteUpdateStateBasic() { + var ( + substitute string + substituteClientState exported.ClientState + initialHeight clienttypes.Height + ) + testCases := []struct { + name string + malleate func() + }{ + { + "solo machine used for substitute", func() { + substituteClientState = ibctesting.NewSolomachine(suite.T(), suite.cdc, "solo machine", "", 1).ClientState() + }, + }, + { + "initial height and substitute revision numbers do not match", func() { + initialHeight = clienttypes.NewHeight(substituteClientState.GetLatestHeight().GetRevisionNumber()+1, 1) + }, + }, + { + "non-matching substitute", func() { + substitute, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + substituteClientState = suite.chainA.GetClientState(substitute).(*types.ClientState) + tmClientState, ok := substituteClientState.(*types.ClientState) + suite.Require().True(ok) + + tmClientState.ChainId = tmClientState.ChainId + "different chain" + }, + }, + { + "updated client is invalid - revision height is zero", func() { + substitute, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + substituteClientState = suite.chainA.GetClientState(substitute).(*types.ClientState) + tmClientState, ok := substituteClientState.(*types.ClientState) + suite.Require().True(ok) + // match subject + tmClientState.AllowUpdateAfterMisbehaviour = true + tmClientState.AllowUpdateAfterExpiry = true + + // will occur. This case should never occur (caught by upstream checks) + initialHeight = clienttypes.NewHeight(5, 0) + tmClientState.LatestHeight = clienttypes.NewHeight(5, 0) + }, + }, + { + "updated client is expired", func() { + substitute, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + substituteClientState = suite.chainA.GetClientState(substitute).(*types.ClientState) + tmClientState, ok := substituteClientState.(*types.ClientState) + suite.Require().True(ok) + initialHeight = tmClientState.LatestHeight + + // match subject + tmClientState.AllowUpdateAfterMisbehaviour = true + tmClientState.AllowUpdateAfterExpiry = true + suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), substitute, tmClientState) + + // update substitute a few times + err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, substitute, exported.Tendermint) + suite.Require().NoError(err) + substituteClientState = suite.chainA.GetClientState(substitute) + + err = suite.coordinator.UpdateClient(suite.chainA, suite.chainB, substitute, exported.Tendermint) + suite.Require().NoError(err) + + suite.chainA.ExpireClient(tmClientState.TrustingPeriod) + suite.chainB.ExpireClient(tmClientState.TrustingPeriod) + suite.coordinator.CommitBlock(suite.chainA, suite.chainB) + + substituteClientState = suite.chainA.GetClientState(substitute) + }, + }, + } + + for _, tc := range testCases { + tc := tc + + suite.Run(tc.name, func() { + + suite.SetupTest() // reset + + subject, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + subjectClientState := suite.chainA.GetClientState(subject).(*types.ClientState) + subjectClientState.AllowUpdateAfterMisbehaviour = true + subjectClientState.AllowUpdateAfterExpiry = true + + // expire subject + suite.chainA.ExpireClient(subjectClientState.TrustingPeriod) + suite.chainB.ExpireClient(subjectClientState.TrustingPeriod) + suite.coordinator.CommitBlock(suite.chainA, suite.chainB) + + tc.malleate() + + subjectClientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), subject) + substituteClientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), substitute) + + updatedClient, err := subjectClientState.CheckSubstituteAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), subjectClientStore, substituteClientStore, substituteClientState, initialHeight) + suite.Require().Error(err) + suite.Require().Nil(updatedClient) + }) + } } // to expire clients, time needs to be fast forwarded on both chainA and chainB. // this is to prevent headers from failing when attempting to update later. -func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateState() { +func (suite *TendermintTestSuite) TestCheckSubstituteAndUpdateState() { testCases := []struct { name string AllowUpdateAfterExpiry bool AllowUpdateAfterMisbehaviour bool FreezeClient bool ExpireClient bool - expPassUnfreeze bool // expected result using a header that passes stronger validation - expPassUnexpire bool // expected result using a header that passes weaker validation + expPass bool }{ { name: "not allowed to be updated, not frozen or expired", @@ -50,8 +134,7 @@ func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateState() { AllowUpdateAfterMisbehaviour: false, FreezeClient: false, ExpireClient: false, - expPassUnfreeze: false, - expPassUnexpire: false, + expPass: false, }, { name: "not allowed to be updated, client is frozen", @@ -59,8 +142,7 @@ func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateState() { AllowUpdateAfterMisbehaviour: false, FreezeClient: true, ExpireClient: false, - expPassUnfreeze: false, - expPassUnexpire: false, + expPass: false, }, { name: "not allowed to be updated, client is expired", @@ -68,8 +150,7 @@ func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateState() { AllowUpdateAfterMisbehaviour: false, FreezeClient: false, ExpireClient: true, - expPassUnfreeze: false, - expPassUnexpire: false, + expPass: false, }, { name: "not allowed to be updated, client is frozen and expired", @@ -77,8 +158,7 @@ func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateState() { AllowUpdateAfterMisbehaviour: false, FreezeClient: true, ExpireClient: true, - expPassUnfreeze: false, - expPassUnexpire: false, + expPass: false, }, { name: "allowed to be updated only after misbehaviour, not frozen or expired", @@ -86,17 +166,7 @@ func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateState() { AllowUpdateAfterMisbehaviour: true, FreezeClient: false, ExpireClient: false, - expPassUnfreeze: false, - expPassUnexpire: false, - }, - { - name: "PASS: allowed to be updated only after misbehaviour, client is frozen", - AllowUpdateAfterExpiry: false, - AllowUpdateAfterMisbehaviour: true, - FreezeClient: true, - ExpireClient: false, - expPassUnfreeze: true, - expPassUnexpire: false, + expPass: false, }, { name: "allowed to be updated only after misbehaviour, client is expired", @@ -104,17 +174,7 @@ func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateState() { AllowUpdateAfterMisbehaviour: true, FreezeClient: false, ExpireClient: true, - expPassUnfreeze: false, - expPassUnexpire: false, - }, - { - name: "allowed to be updated only after misbehaviour, client is frozen and expired", - AllowUpdateAfterExpiry: false, - AllowUpdateAfterMisbehaviour: true, - FreezeClient: true, - ExpireClient: true, - expPassUnfreeze: true, - expPassUnexpire: true, + expPass: false, }, { name: "allowed to be updated only after expiry, not frozen or expired", @@ -122,8 +182,7 @@ func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateState() { AllowUpdateAfterMisbehaviour: false, FreezeClient: false, ExpireClient: false, - expPassUnfreeze: false, - expPassUnexpire: false, + expPass: false, }, { name: "allowed to be updated only after expiry, client is frozen", @@ -131,8 +190,23 @@ func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateState() { AllowUpdateAfterMisbehaviour: false, FreezeClient: true, ExpireClient: false, - expPassUnfreeze: false, - expPassUnexpire: false, + expPass: false, + }, + { + name: "PASS: allowed to be updated only after misbehaviour, client is frozen", + AllowUpdateAfterExpiry: false, + AllowUpdateAfterMisbehaviour: true, + FreezeClient: true, + ExpireClient: false, + expPass: true, + }, + { + name: "PASS: allowed to be updated only after misbehaviour, client is frozen and expired", + AllowUpdateAfterExpiry: false, + AllowUpdateAfterMisbehaviour: true, + FreezeClient: true, + ExpireClient: true, + expPass: true, }, { name: "PASS: allowed to be updated only after expiry, client is expired", @@ -140,8 +214,7 @@ func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateState() { AllowUpdateAfterMisbehaviour: false, FreezeClient: false, ExpireClient: true, - expPassUnfreeze: true, - expPassUnexpire: true, + expPass: true, }, { name: "allowed to be updated only after expiry, client is frozen and expired", @@ -149,8 +222,7 @@ func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateState() { AllowUpdateAfterMisbehaviour: false, FreezeClient: true, ExpireClient: true, - expPassUnfreeze: false, - expPassUnexpire: false, + expPass: false, }, { name: "allowed to be updated after expiry and misbehaviour, not frozen or expired", @@ -158,8 +230,7 @@ func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateState() { AllowUpdateAfterMisbehaviour: true, FreezeClient: false, ExpireClient: false, - expPassUnfreeze: false, - expPassUnexpire: false, + expPass: false, }, { name: "PASS: allowed to be updated after expiry and misbehaviour, client is frozen", @@ -167,8 +238,7 @@ func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateState() { AllowUpdateAfterMisbehaviour: true, FreezeClient: true, ExpireClient: false, - expPassUnfreeze: true, - expPassUnexpire: false, + expPass: true, }, { name: "PASS: allowed to be updated after expiry and misbehaviour, client is expired", @@ -176,8 +246,7 @@ func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateState() { AllowUpdateAfterMisbehaviour: true, FreezeClient: false, ExpireClient: true, - expPassUnfreeze: true, - expPassUnexpire: true, + expPass: true, }, { name: "PASS: allowed to be updated after expiry and misbehaviour, client is frozen and expired", @@ -185,8 +254,7 @@ func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateState() { AllowUpdateAfterMisbehaviour: true, FreezeClient: true, ExpireClient: true, - expPassUnfreeze: true, - expPassUnexpire: true, + expPass: true, }, } @@ -201,67 +269,67 @@ func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateState() { // start by testing unexpiring the client suite.SetupTest() // reset - // construct client state based on test case parameters - clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - clientState := suite.chainA.GetClientState(clientA).(*types.ClientState) - clientState.AllowUpdateAfterExpiry = tc.AllowUpdateAfterExpiry - clientState.AllowUpdateAfterMisbehaviour = tc.AllowUpdateAfterMisbehaviour + // construct subject using test case parameters + subject, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + subjectClientState := suite.chainA.GetClientState(subject).(*types.ClientState) + subjectClientState.AllowUpdateAfterExpiry = tc.AllowUpdateAfterExpiry + subjectClientState.AllowUpdateAfterMisbehaviour = tc.AllowUpdateAfterMisbehaviour + + // apply freezing or expiry as determined by the test case if tc.FreezeClient { - clientState.FrozenHeight = frozenHeight + subjectClientState.FrozenHeight = frozenHeight } if tc.ExpireClient { - suite.chainA.ExpireClient(clientState.TrustingPeriod) - suite.chainB.ExpireClient(clientState.TrustingPeriod) + suite.chainA.ExpireClient(subjectClientState.TrustingPeriod) + suite.chainB.ExpireClient(subjectClientState.TrustingPeriod) suite.coordinator.CommitBlock(suite.chainA, suite.chainB) } - // use next header for chainB to unfreeze client on chainA - unfreezeClientHeader, err := suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, clientA) - suite.Require().NoError(err) + // construct the substitute to match the subject client + // NOTE: the substitute is explicitly created after the freezing or expiry occurs, + // primarily to prevent the substitute from becoming frozen. It also should be + // the natural flow of events in practice. The subject will become frozen/expired + // and a substitute will be created along with a governance proposal as a response - clientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA) - cs, consState, err := clientState.CheckProposedHeaderAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, unfreezeClientHeader) + substitute, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + substituteClientState := suite.chainA.GetClientState(substitute).(*types.ClientState) + substituteClientState.AllowUpdateAfterExpiry = tc.AllowUpdateAfterExpiry + substituteClientState.AllowUpdateAfterMisbehaviour = tc.AllowUpdateAfterMisbehaviour + suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), substitute, substituteClientState) - if tc.expPassUnfreeze { + initialHeight := substituteClientState.GetLatestHeight() + + // update substitute a few times + for i := 0; i < 3; i++ { + err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, substitute, exported.Tendermint) suite.Require().NoError(err) - suite.Require().Equal(clienttypes.ZeroHeight(), cs.GetFrozenHeight()) - suite.Require().NotNil(consState) - } else { - suite.Require().Error(err) - suite.Require().Nil(cs) - suite.Require().Nil(consState) + // skip a block + suite.coordinator.CommitBlock(suite.chainA, suite.chainB) } - // use next header for chainB to unexpire clients but with empty trusted heights - // and validators. Update chainB time so header won't be expired. - unexpireClientHeader, err := suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, clientA) - suite.Require().NoError(err) - unexpireClientHeader.TrustedHeight = clienttypes.ZeroHeight() - unexpireClientHeader.TrustedValidators = nil + // get updated substitue + substituteClientState = suite.chainA.GetClientState(substitute).(*types.ClientState) - clientStore = suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA) - cs, consState, err = clientState.CheckProposedHeaderAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, unexpireClientHeader) + subjectClientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), subject) + substituteClientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), substitute) + updatedClient, err := subjectClientState.CheckSubstituteAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), subjectClientStore, substituteClientStore, substituteClientState, initialHeight) - if tc.expPassUnexpire { + if tc.expPass { suite.Require().NoError(err) - suite.Require().NotNil(cs) - suite.Require().NotNil(consState) + suite.Require().Equal(clienttypes.ZeroHeight(), updatedClient.GetFrozenHeight()) } else { suite.Require().Error(err) - suite.Require().Nil(cs) - suite.Require().Nil(consState) + suite.Require().Nil(updatedClient) } + }) } } -// test softer validation on headers used for unexpiring clients -func (suite *TendermintTestSuite) TestCheckProposedHeader() { +func (suite *TendermintTestSuite) TestIsMatchingClientState() { var ( - header *types.Header - clientState *types.ClientState - clientA string - err error + subject, substitute string + subjectClientState, substituteClientState *types.ClientState ) testCases := []struct { @@ -270,46 +338,33 @@ func (suite *TendermintTestSuite) TestCheckProposedHeader() { expPass bool }{ { - "success", func() {}, true, + "matching clients", func() { + subjectClientState = suite.chainA.GetClientState(subject).(*types.ClientState) + substituteClientState = suite.chainA.GetClientState(substitute).(*types.ClientState) + }, true, }, { - "invalid signed header", func() { - header.SignedHeader = nil - }, false, + "matching, frozen height is not used in check for equality", func() { + subjectClientState.FrozenHeight = frozenHeight + substituteClientState.FrozenHeight = clienttypes.ZeroHeight() + }, true, }, { - "header time is less than or equal to consensus state timestamp", func() { - consensusState, found := suite.chainA.GetConsensusState(clientA, clientState.GetLatestHeight()) - suite.Require().True(found) - consensusState.(*types.ConsensusState).Timestamp = header.GetTime() - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), clientA, clientState.GetLatestHeight(), consensusState) - - // update block time so client is expired - suite.chainA.ExpireClient(clientState.TrustingPeriod) - suite.chainB.ExpireClient(clientState.TrustingPeriod) - suite.coordinator.CommitBlock(suite.chainA, suite.chainB) - }, false, + "matching, latest height is not used in check for equality", func() { + subjectClientState.LatestHeight = clienttypes.NewHeight(0, 10) + substituteClientState.FrozenHeight = clienttypes.ZeroHeight() + }, true, }, { - "header height is not newer than client state", func() { - consensusState, found := suite.chainA.GetConsensusState(clientA, clientState.GetLatestHeight()) - suite.Require().True(found) - clientState.LatestHeight = header.GetHeight().(clienttypes.Height) - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), clientA, clientState.GetLatestHeight(), consensusState) - - }, false, + "matching, chain id is different", func() { + subjectClientState.ChainId = "bitcoin" + substituteClientState.ChainId = "ethereum" + }, true, }, { - "signed header failed validate basic - wrong chain ID", func() { - clientState.ChainId = ibctesting.InvalidID - }, false, - }, - { - "header is already expired", func() { - // expire client - suite.chainA.ExpireClient(clientState.TrustingPeriod) - suite.chainB.ExpireClient(clientState.TrustingPeriod) - suite.coordinator.CommitBlock(suite.chainA, suite.chainB) + "not matching, trusting period is different", func() { + subjectClientState.TrustingPeriod = time.Duration(time.Hour * 10) + substituteClientState.TrustingPeriod = time.Duration(time.Hour * 1) }, false, }, } @@ -320,37 +375,13 @@ func (suite *TendermintTestSuite) TestCheckProposedHeader() { suite.Run(tc.name, func() { suite.SetupTest() // reset - clientA, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - clientState = suite.chainA.GetClientState(clientA).(*types.ClientState) - clientState.AllowUpdateAfterExpiry = true - clientState.AllowUpdateAfterMisbehaviour = false - - // expire client - suite.chainA.ExpireClient(clientState.TrustingPeriod) - suite.chainB.ExpireClient(clientState.TrustingPeriod) - suite.coordinator.CommitBlock(suite.chainA, suite.chainB) - - // use next header for chainB to unexpire clients but with empty trusted heights - // and validators. - header, err = suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, clientA) - suite.Require().NoError(err) - header.TrustedHeight = clienttypes.ZeroHeight() - header.TrustedValidators = nil + subject, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + substitute, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) tc.malleate() - clientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA) - cs, consState, err := clientState.CheckProposedHeaderAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, header) + suite.Require().Equal(tc.expPass, types.IsMatchingClientState(*subjectClientState, *substituteClientState)) - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(cs) - suite.Require().NotNil(consState) - } else { - suite.Require().Error(err) - suite.Require().Nil(cs) - suite.Require().Nil(consState) - } }) } } diff --git a/x/ibc/light-clients/07-tendermint/types/store.go b/x/ibc/light-clients/07-tendermint/types/store.go index 8b2720c5a995..7d6a841b89f1 100644 --- a/x/ibc/light-clients/07-tendermint/types/store.go +++ b/x/ibc/light-clients/07-tendermint/types/store.go @@ -14,6 +14,13 @@ import ( // KeyProcessedTime is appended to consensus state key to store the processed time var KeyProcessedTime = []byte("/processedTime") +// SetConsensusState stores the consensus state at the given height. +func SetConsensusState(clientStore sdk.KVStore, cdc codec.BinaryMarshaler, consensusState *ConsensusState, height exported.Height) { + key := host.ConsensusStateKey(height) + val := clienttypes.MustMarshalConsensusState(cdc, consensusState) + clientStore.Set(key, val) +} + // GetConsensusState retrieves the consensus state from the client prefixed // store. An error is returned if the consensus state does not exist. func GetConsensusState(store sdk.KVStore, cdc codec.BinaryMarshaler, height exported.Height) (*ConsensusState, error) { diff --git a/x/ibc/light-clients/09-localhost/types/client_state.go b/x/ibc/light-clients/09-localhost/types/client_state.go index e0ba7a2f0b20..5a4a41a17988 100644 --- a/x/ibc/light-clients/09-localhost/types/client_state.go +++ b/x/ibc/light-clients/09-localhost/types/client_state.go @@ -107,12 +107,13 @@ func (cs ClientState) CheckMisbehaviourAndUpdateState( return nil, sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "cannot submit misbehaviour to localhost client") } -// CheckProposedHeaderAndUpdateState returns an error. The localhost cannot be modified by +// CheckSubstituteAndUpdateState returns an error. The localhost cannot be modified by // proposals. -func (cs ClientState) CheckProposedHeaderAndUpdateState( - ctx sdk.Context, _ codec.BinaryMarshaler, _ sdk.KVStore, _ exported.Header, -) (exported.ClientState, exported.ConsensusState, error) { - return nil, nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "cannot update localhost client with a proposal") +func (cs ClientState) CheckSubstituteAndUpdateState( + ctx sdk.Context, _ codec.BinaryMarshaler, _, _ sdk.KVStore, + _ exported.ClientState, _ exported.Height, +) (exported.ClientState, error) { + return nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "cannot update localhost client with a proposal") } // VerifyUpgradeAndUpdateState returns an error since localhost cannot be upgraded diff --git a/x/ibc/light-clients/09-localhost/types/client_state_test.go b/x/ibc/light-clients/09-localhost/types/client_state_test.go index 13a1367d5c21..bc58f62539be 100644 --- a/x/ibc/light-clients/09-localhost/types/client_state_test.go +++ b/x/ibc/light-clients/09-localhost/types/client_state_test.go @@ -170,10 +170,9 @@ func (suite *LocalhostTestSuite) TestMisbehaviourAndUpdateState() { func (suite *LocalhostTestSuite) TestProposedHeaderAndUpdateState() { clientState := types.NewClientState("chainID", clientHeight) - cs, consState, err := clientState.CheckProposedHeaderAndUpdateState(suite.ctx, nil, nil, nil) + cs, err := clientState.CheckSubstituteAndUpdateState(suite.ctx, nil, nil, nil, nil, nil) suite.Require().Error(err) suite.Require().Nil(cs) - suite.Require().Nil(consState) } func (suite *LocalhostTestSuite) TestVerifyConnectionState() { From 56fc3fc5726a38e4fd379cc1dc245df6e71ba9f6 Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Wed, 17 Feb 2021 02:13:00 -0800 Subject: [PATCH 138/152] codec/types: avoid unnecessary allocations for NewAnyWithCustomTypeURL on error (#8605) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoids a bleed out attack in which a node can be made to allocate memory slowly or very fast in small strides, by sending bad data to code that invokes NewAnyWithCustomTypeURL, in which we unconditionally returned a new Any object. On a 64-bit machine, this would waste 96 bytes per invocation even on error. Added a test to ensure zero allocations with a fixed error returned. Also added a benchmark which shows reduction in wasted allocations and wasted CPU time: ```shell $ benchstat before.txt after.txt name old time/op new time/op delta NewAnyWithCustomTypeURLWithErrorReturned-8 142ns ± 6% 55ns ±12% -61.65% (p=0.000 n=9+10) name old alloc/op new alloc/op delta NewAnyWithCustomTypeURLWithErrorReturned-8 96.0B ± 0% 0.0B -100.00% (p=0.000 n=10+10) name old allocs/op new allocs/op delta NewAnyWithCustomTypeURLWithErrorReturned-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) ``` Fixes #8537 --- codec/types/any.go | 5 ++- codec/types/any_test.go | 68 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 codec/types/any_test.go diff --git a/codec/types/any.go b/codec/types/any.go index c33931f0e22f..1d9d34ff2a22 100644 --- a/codec/types/any.go +++ b/codec/types/any.go @@ -71,11 +71,14 @@ func NewAnyWithValue(v proto.Message) (*Any, error) { // into the protobuf Any serialization. For simple marshaling you should use NewAnyWithValue. func NewAnyWithCustomTypeURL(v proto.Message, typeURL string) (*Any, error) { bz, err := proto.Marshal(v) + if err != nil { + return nil, err + } return &Any{ TypeUrl: typeURL, Value: bz, cachedValue: v, - }, err + }, nil } // UnsafePackAny packs the value x in the Any and instead of returning the error diff --git a/codec/types/any_test.go b/codec/types/any_test.go new file mode 100644 index 000000000000..cea3e0444efb --- /dev/null +++ b/codec/types/any_test.go @@ -0,0 +1,68 @@ +package types_test + +import ( + "fmt" + "runtime" + "testing" + + "github.com/gogo/protobuf/proto" + + "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/testutil/testdata" +) + +type errOnMarshal struct { + testdata.Dog +} + +var _ proto.Message = (*errOnMarshal)(nil) + +var errAlways = fmt.Errorf("always erroring") + +func (eom *errOnMarshal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return nil, errAlways +} + +const fauxURL = "/anyhere" + +var eom = &errOnMarshal{} + +// Ensure that returning an error doesn't suddenly allocate and waste bytes. +// See https://github.com/cosmos/cosmos-sdk/issues/8537 +func TestNewAnyWithCustomTypeURLWithErrorNoAllocation(t *testing.T) { + var ms1, ms2 runtime.MemStats + runtime.ReadMemStats(&ms1) + any, err := types.NewAnyWithCustomTypeURL(eom, fauxURL) + runtime.ReadMemStats(&ms2) + // Ensure that no fresh allocation was made. + if diff := ms2.HeapAlloc - ms1.HeapAlloc; diff > 0 { + t.Errorf("Unexpected allocation of %d bytes", diff) + } + if err == nil { + t.Fatal("err wasn't returned") + } + if any != nil { + t.Fatalf("Unexpectedly got a non-nil Any value: %v", any) + } +} + +var sink interface{} + +func BenchmarkNewAnyWithCustomTypeURLWithErrorReturned(b *testing.B) { + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + any, err := types.NewAnyWithCustomTypeURL(eom, fauxURL) + if err == nil { + b.Fatal("err wasn't returned") + } + if any != nil { + b.Fatalf("Unexpectedly got a non-nil Any value: %v", any) + } + sink = any + } + if sink == nil { + b.Fatal("benchmark didn't run") + } + sink = (interface{})(nil) +} From f970056a92a77f38f9b15fd328568d8110946cc9 Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Wed, 17 Feb 2021 02:30:04 -0800 Subject: [PATCH 139/152] crypto/hd: make DerivePrivateKeyForPath error and not panic on trailing slashes (#8607) Detected during my audit, right before fuzzing, the code that checked for presence of hyphens per path segment assumed that the part would always be non-empty. However, with paths such as: * m/4/ * /44/ * m/4/// it'd panic with a runtime slice out of bounds. With this new change, we now: * firstly strip the right trailing slash * on finding any empty segments of a path return an error Fixes #8557 --- crypto/hd/hdpath.go | 9 ++++++++- crypto/hd/hdpath_test.go | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/crypto/hd/hdpath.go b/crypto/hd/hdpath.go index 04469d730591..058ddcc45667 100644 --- a/crypto/hd/hdpath.go +++ b/crypto/hd/hdpath.go @@ -6,6 +6,7 @@ import ( "encoding/binary" "fmt" "math/big" + "path/filepath" "strconv" "strings" @@ -177,6 +178,9 @@ func ComputeMastersFromSeed(seed []byte) (secret [32]byte, chainCode [32]byte) { // DerivePrivateKeyForPath derives the private key by following the BIP 32/44 path from privKeyBytes, // using the given chainCode. func DerivePrivateKeyForPath(privKeyBytes, chainCode [32]byte, path string) ([]byte, error) { + // First step is to trim the right end path separator lest we panic. + // See issue https://github.com/cosmos/cosmos-sdk/issues/8557 + path = strings.TrimRightFunc(path, func(r rune) bool { return r == filepath.Separator }) data := privKeyBytes parts := strings.Split(path, "/") @@ -187,7 +191,10 @@ func DerivePrivateKeyForPath(privKeyBytes, chainCode [32]byte, path string) ([]b parts = parts[1:] } - for _, part := range parts { + for i, part := range parts { + if part == "" { + return nil, fmt.Errorf("path %q with split element #%d is an empty string", part, i) + } // do we have an apostrophe? harden := part[len(part)-1:] == "'" // harden == private derivation, else public derivation: diff --git a/crypto/hd/hdpath_test.go b/crypto/hd/hdpath_test.go index 6dfda043eb04..8b1c40692c82 100644 --- a/crypto/hd/hdpath_test.go +++ b/crypto/hd/hdpath_test.go @@ -281,3 +281,26 @@ func ExampleSomeBIP32TestVecs() { // // c4c11d8c03625515905d7e89d25dfc66126fbc629ecca6db489a1a72fc4bda78 } + +// Ensuring that we don't crash if values have trailing slashes +// See issue https://github.com/cosmos/cosmos-sdk/issues/8557. +func TestDerivePrivateKeyForPathDoNotCrash(t *testing.T) { + paths := []string{ + "m/5/", + "m/5", + "/44", + "m//5", + "m/0/7", + "/", + " m  /0/7", // Test case from fuzzer + "  /  ", // Test case from fuzzer + "m///7//////", + } + + for _, path := range paths { + path := path + t.Run(path, func(t *testing.T) { + hd.DerivePrivateKeyForPath([32]byte{}, [32]byte{}, path) + }) + } +} From d56de85a542b7a56730b8edc18da42032a7f91de Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Wed, 17 Feb 2021 03:04:43 -0800 Subject: [PATCH 140/152] =?UTF-8?q?x/gov/simulation:=20fix=20wrong=20NewDe?= =?UTF-8?q?codeStore=C2=A0Proposal=20decoding=20+=20proper=20tests=20(#860?= =?UTF-8?q?3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code in NewDecodeStore decoded the wrong proposal due to a typographical error, but the tests used the exact same value for the key value pairs hence the typo could never be caught. I noticed it during an audit of the code, and I've fixed the tests to pass in varying values for the various key value pairs. Fixes #8570 Co-authored-by: Alessio Treglia --- x/gov/simulation/decoder.go | 2 +- x/gov/simulation/decoder_test.go | 68 +++++++++++++++++++++----------- 2 files changed, 45 insertions(+), 25 deletions(-) diff --git a/x/gov/simulation/decoder.go b/x/gov/simulation/decoder.go index 75cb4a5fccc8..180754ddee08 100644 --- a/x/gov/simulation/decoder.go +++ b/x/gov/simulation/decoder.go @@ -22,7 +22,7 @@ func NewDecodeStore(cdc codec.Marshaler) func(kvA, kvB kv.Pair) string { panic(err) } var proposalB types.Proposal - err = cdc.UnmarshalBinaryBare(kvA.Value, &proposalB) + err = cdc.UnmarshalBinaryBare(kvB.Value, &proposalB) if err != nil { panic(err) } diff --git a/x/gov/simulation/decoder_test.go b/x/gov/simulation/decoder_test.go index 1d733b1b82ae..4f6273a171e4 100644 --- a/x/gov/simulation/decoder_test.go +++ b/x/gov/simulation/decoder_test.go @@ -27,7 +27,9 @@ func TestDecodeStore(t *testing.T) { endTime := time.Now().UTC() content := types.ContentFromProposalType("test", "test", types.ProposalTypeText) - proposal, err := types.NewProposal(content, 1, endTime, endTime.Add(24*time.Hour)) + proposalA, err := types.NewProposal(content, 1, endTime, endTime.Add(24*time.Hour)) + require.NoError(t, err) + proposalB, err := types.NewProposal(content, 2, endTime, endTime.Add(24*time.Hour)) require.NoError(t, err) proposalIDBz := make([]byte, 8) @@ -35,38 +37,56 @@ func TestDecodeStore(t *testing.T) { deposit := types.NewDeposit(1, delAddr1, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt()))) vote := types.NewVote(1, delAddr1, types.NewNonSplitVoteOption(types.OptionYes)) - proposalBz, err := cdc.MarshalBinaryBare(&proposal) + proposalBzA, err := cdc.MarshalBinaryBare(&proposalA) + require.NoError(t, err) + proposalBzB, err := cdc.MarshalBinaryBare(&proposalB) require.NoError(t, err) - - kvPairs := kv.Pairs{ - Pairs: []kv.Pair{ - {Key: types.ProposalKey(1), Value: proposalBz}, - {Key: types.InactiveProposalQueueKey(1, endTime), Value: proposalIDBz}, - {Key: types.DepositKey(1, delAddr1), Value: cdc.MustMarshalBinaryBare(&deposit)}, - {Key: types.VoteKey(1, delAddr1), Value: cdc.MustMarshalBinaryBare(&vote)}, - {Key: []byte{0x99}, Value: []byte{0x99}}, - }, - } tests := []struct { name string + kvA, kvB kv.Pair expectedLog string + wantPanic bool }{ - {"proposals", fmt.Sprintf("%v\n%v", proposal, proposal)}, - {"proposal IDs", "proposalIDA: 1\nProposalIDB: 1"}, - {"deposits", fmt.Sprintf("%v\n%v", deposit, deposit)}, - {"votes", fmt.Sprintf("%v\n%v", vote, vote)}, - {"other", ""}, + { + "proposals", + kv.Pair{Key: types.ProposalKey(1), Value: proposalBzA}, + kv.Pair{Key: types.ProposalKey(2), Value: proposalBzB}, + fmt.Sprintf("%v\n%v", proposalA, proposalB), false, + }, + { + "proposal IDs", + kv.Pair{Key: types.InactiveProposalQueueKey(1, endTime), Value: proposalIDBz}, + kv.Pair{Key: types.InactiveProposalQueueKey(1, endTime), Value: proposalIDBz}, + "proposalIDA: 1\nProposalIDB: 1", false, + }, + { + "deposits", + kv.Pair{Key: types.DepositKey(1, delAddr1), Value: cdc.MustMarshalBinaryBare(&deposit)}, + kv.Pair{Key: types.DepositKey(1, delAddr1), Value: cdc.MustMarshalBinaryBare(&deposit)}, + fmt.Sprintf("%v\n%v", deposit, deposit), false, + }, + { + "votes", + kv.Pair{Key: types.VoteKey(1, delAddr1), Value: cdc.MustMarshalBinaryBare(&vote)}, + kv.Pair{Key: types.VoteKey(1, delAddr1), Value: cdc.MustMarshalBinaryBare(&vote)}, + fmt.Sprintf("%v\n%v", vote, vote), false, + }, + { + "other", + kv.Pair{Key: []byte{0x99}, Value: []byte{0x99}}, + kv.Pair{Key: []byte{0x99}, Value: []byte{0x99}}, + "", true, + }, } - for i, tt := range tests { - i, tt := i, tt + for _, tt := range tests { + tt := tt t.Run(tt.name, func(t *testing.T) { - switch i { - case len(tests) - 1: - require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) - default: - require.Equal(t, tt.expectedLog, dec(kvPairs.Pairs[i], kvPairs.Pairs[i]), tt.name) + if tt.wantPanic { + require.Panics(t, func() { dec(tt.kvA, tt.kvB) }, tt.name) + } else { + require.Equal(t, tt.expectedLog, dec(tt.kvA, tt.kvB), tt.name) } }) } From cc215d6097a974ca53e21408abce86d695648bc6 Mon Sep 17 00:00:00 2001 From: Cory Date: Wed, 17 Feb 2021 04:41:08 -0800 Subject: [PATCH 141/152] Update master CHANGELOG.md with v0.41, enable building docs for v0.41 (#8562) * pull changelog updates in from v0.41.0 release * update docs versions file to only build off release/v0.41.x release branch for Stargate docs * Update CHANGELOG.md Co-authored-by: Robert Zaremba Co-authored-by: Amaury M <1293565+amaurym@users.noreply.github.com> Co-authored-by: Robert Zaremba --- CHANGELOG.md | 15 ++++++++++++--- docs/versions | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c39a1780e9aa..934cca757142 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,21 +56,30 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/ibc) [\#8458](https://github.com/cosmos/cosmos-sdk/pull/8458) Add `packet_connection` attribute to ibc events to enable relayer filtering * (x/bank) [\#8479](https://github.com/cosmos/cosmos-sdk/pull/8479) Adittional client denom metadata validation for `base` and `display` denoms. -* (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks. * [\#8396](https://github.com/cosmos/cosmos-sdk/pull/8396) Add support for ARM platform ### Bug Fixes * (x/evidence) [#8461](https://github.com/cosmos/cosmos-sdk/pull/8461) Fix bech32 prefix in evidence validator address conversion * (x/slashing) [\#8427](https://github.com/cosmos/cosmos-sdk/pull/8427) Fix query signing infos command -* (simapp) [\#8418](https://github.com/cosmos/cosmos-sdk/pull/8418) Add balance coin to supply when adding a new genesis account -* (x/bank) [\#8417](https://github.com/cosmos/cosmos-sdk/pull/8417) Validate balances and coin denom metadata on genesis * (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value * (client/keys) [\#8436](https://github.com/cosmos/cosmos-sdk/pull/8436) Fix key migration issue * (server) [\#8481](https://github.com/cosmos/cosmos-sdk/pull/8481) Don't create files when running `{appd} tendermint show-*` subcommands * (x/staking) [\#8546](https://github.com/cosmos/cosmos-sdk/pull/8546) Fix caching bug where concurrent calls to GetValidator could cause a node to crash +## [v0.41.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.41.0) - 2021-01-26 + +### State Machine Breaking + +* (x/ibc) [\#8266](https://github.com/cosmos/cosmos-sdk/issues/8266) Add amino JSON support for IBC MsgTransfer in order to support Ledger text signing transfer transactions. +* (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks. + +### Bug Fixes + +* (simapp) [\#8418](https://github.com/cosmos/cosmos-sdk/pull/8418) Add balance coin to supply when adding a new genesis account +* (x/bank) [\#8417](https://github.com/cosmos/cosmos-sdk/pull/8417) Validate balances and coin denom metadata on genesis + ## [v0.40.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.1) - 2021-01-19 ### Improvements diff --git a/docs/versions b/docs/versions index d4be1796400d..31c880a13dde 100644 --- a/docs/versions +++ b/docs/versions @@ -1,3 +1,3 @@ master master launchpad/backports v0.39 -release/v0.40.x v0.40 +release/v0.41.x v0.41 From 50dec2e9fad28cd51351387414f4e387c992beda Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Wed, 17 Feb 2021 14:40:59 +0100 Subject: [PATCH 142/152] Add v0.41.1 section in Changelog (#8610) --- CHANGELOG.md | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 934cca757142..368cdd90a88f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,19 +54,29 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements -* (x/ibc) [\#8458](https://github.com/cosmos/cosmos-sdk/pull/8458) Add `packet_connection` attribute to ibc events to enable relayer filtering -* (x/bank) [\#8479](https://github.com/cosmos/cosmos-sdk/pull/8479) Adittional client denom metadata validation for `base` and `display` denoms. -* [\#8396](https://github.com/cosmos/cosmos-sdk/pull/8396) Add support for ARM platform ### Bug Fixes * (x/evidence) [#8461](https://github.com/cosmos/cosmos-sdk/pull/8461) Fix bech32 prefix in evidence validator address conversion * (x/slashing) [\#8427](https://github.com/cosmos/cosmos-sdk/pull/8427) Fix query signing infos command * (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value -* (client/keys) [\#8436](https://github.com/cosmos/cosmos-sdk/pull/8436) Fix key migration issue -* (server) [\#8481](https://github.com/cosmos/cosmos-sdk/pull/8481) Don't create - files when running `{appd} tendermint show-*` subcommands + +## [v0.41.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.41.1) - 2021-02-17 + +### Bug Fixes + +* (grpc) [\#8549](https://github.com/cosmos/cosmos-sdk/pull/8549) Make gRPC requests go through ABCI and disallow concurrency. * (x/staking) [\#8546](https://github.com/cosmos/cosmos-sdk/pull/8546) Fix caching bug where concurrent calls to GetValidator could cause a node to crash +* (server) [\#8481](https://github.com/cosmos/cosmos-sdk/pull/8481) Don't create files when running `{appd} tendermint show-*` subcommands. +* (client/keys) [\#8436](https://github.com/cosmos/cosmos-sdk/pull/8436) Fix keybase->keyring keys migration. +* (crypto/hd) [\#8607](https://github.com/cosmos/cosmos-sdk/pull/8607) Make DerivePrivateKeyForPath error and not panic on trailing slashes. + +### Improvements + +* (x/ibc) [\#8458](https://github.com/cosmos/cosmos-sdk/pull/8458) Add `packet_connection` attribute to ibc events to enable relayer filtering +* [\#8396](https://github.com/cosmos/cosmos-sdk/pull/8396) Add support for ARM platform +* (x/bank) [\#8479](https://github.com/cosmos/cosmos-sdk/pull/8479) Aditional client denom metadata validation for `base` and `display` denoms. +* (codec/types) [\#8605](https://github.com/cosmos/cosmos-sdk/pull/8605) Avoid unnecessary allocations for NewAnyWithCustomTypeURL on error. ## [v0.41.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.41.0) - 2021-01-26 From 0bcc4027906e3f25ab51b396f222584c6bd9c182 Mon Sep 17 00:00:00 2001 From: Marko Date: Wed, 17 Feb 2021 15:15:22 +0000 Subject: [PATCH 143/152] add backport label to prs (#8609) Backport a PR by just adding the target branch's label, e.g. backport-to-v0.41.x. Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> Co-authored-by: Alessio Treglia --- .mergify.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.mergify.yml b/.mergify.yml index fbf9d7015ae8..ed1892e5cbae 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -8,3 +8,11 @@ pull_request_rules: merge: method: squash strict: true + - name: backport patches to v0.41.x branch + conditions: + - base=master + - label=backport/0.41.x (Stargate) + actions: + backport: + branches: + - release/v0.41.x From abb3dfefa0bfba88c10c4134b2934ce51aa709a2 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Wed, 17 Feb 2021 19:20:33 +0100 Subject: [PATCH 144/152] [Bank] Remove the unsafe balance changing API (#8473) * temp commit * setbalance now is internal * remove set balances in genesis * feedback test commit * update tests * fix: genesis panic message * fix not bonded pool * fix(staking): genesis test * fix(simapp): rollback state fix change * fix(staking): genesis large val set test * [Bank Refactor] Frojdi jonathan/remove setsupply (#8491) * init supply in a different way * remove external usage of set supply * change(staking): replace SetSupply with MintCoins in tests * change(evidence): replace SetSupply with MintCoins in tests * change(crisis): remove SetSupply in tests * change(bank): remove set supply from genesis tests * change(bank): remove set supply from keeper tests * change(bank): remove remaining set supply usage from keeper tests * change(bank): remove set supply usage from grpc query and querier tests * change(bank): remove SetSupply from keeper interface Co-authored-by: Frojdi Dymylja * remove setbalances from genesis in gov * remove keyring * add init genesis state * change(staking): make genesis checks coherent and add tests * remove setbalances on distribution * fix(staking): genesis tests * [Bank Refactor]: Remove SetBalances usage from the code and tests (#8509) * change(distribution): remove SetBalances usage from keeper tests * add(simapp): FundAccount utility function * chore(staking): use FundAccount in keeper tests * change(staking): remove usage of SetBalance in allocation tests * change(staking): remove usage of SetBalance in delegation tests * change(staking): remove usage of SetBalance in proposal handler tests * change(staking): remove usage of SetBalances in grpc query tests * change(staking): remove usage of SetBalances in operations tests * change(distribution): remove usage of SetBalances in genesis * change(authz): remove usage of SetBalances keeper and operations test * fix(authz): TestKeeperFees failing test * change(slashing): remove SetBalances from expected BankKeeper * change(slashing): remove usage of SetBalances in tests * change(distribution): remove SetBalances from expected BankKeeper * change(genutil): remove usage of SetBalances from tests * change(gov): remove SetBalances from expected BankKeeper * change(gov): remove usage of SetBalances from tests * change(staking): remove usage of SetBalances from slash tests * change(staking): remove SetBalances from expected BankKeeper * change(staking): remove usage of SetBalances from delegation tests * change(staking): remove usage of SetBalances from operations tests * change(staking): remove usage of SetBalances from validator tests * change(bank): remove usage of SetBalances from app tests * change(bank): remove usage of SetBalances from bench tests * change(bank): remove usage of SetBalances from querier tests * change(bank): remove usage of SetBalances from grpc query tests * change(bank): remove usage of SetBalances from operations tests * change(bank): partially remove usage of SetBalances from keeper tests * change(bank): finalize removal of usage of SetBalances from keeper tests * change(auth): remove usage of SetBalances from verify tests * change(auth): partially remove usage of SetBalances from tests * [Bank refactor]: finalize removal of setbalances from auth (#8527) * add tests with is check tx * temp commit * fix test * fix other test and remove setbalances * change(auth): remove usage of SetBalances is vesting tests Co-authored-by: Jonathan Gimeno * change(types): remove usage of SetBalances in queries * fix(types): pagination tests * [Bank refactor] fix pagination tests (#8550) * fix tests * lint * change(bank): remove SetBalances from keeper public API Co-authored-by: Jonathan Gimeno Co-authored-by: SaReN * change(bank): remove SubtractCoins from keeper public API * change(ibc/transfer): remove AddCoins from relay tests * change(bank): remove AddCoins from public keeper API * fix imports * remove set balances * fix fee test * remove set balances * fix(staking): remove dependency on minter authorization for staking pools * chore: update CHANGELOG.md * update: x/distribution/keeper/keeper_test.go Co-authored-by: Robert Zaremba * Update simapp/test_helpers.go Co-authored-by: Robert Zaremba * Update x/staking/genesis_test.go Co-authored-by: Robert Zaremba * fix(simapp): FundAccount amount variable name * fix some PR issues Co-authored-by: Frojdi Dymylja Co-authored-by: Frojdi Dymylja <33157909+fdymylja@users.noreply.github.com> Co-authored-by: SaReN Co-authored-by: Alessio Treglia Co-authored-by: Robert Zaremba --- CHANGELOG.md | 5 +- simapp/state.go | 54 ++++++ simapp/test_helpers.go | 48 ++--- types/query/filtered_pagination_test.go | 8 +- types/query/pagination_test.go | 8 +- x/auth/ante/ante_test.go | 31 ++- x/auth/ante/fee_test.go | 11 +- x/auth/ante/testutil_test.go | 11 +- x/auth/signing/verify_test.go | 4 +- x/auth/vesting/handler_test.go | 2 +- x/authz/keeper/keeper_test.go | 25 +-- x/authz/simulation/operations_test.go | 3 +- x/bank/app_test.go | 29 +-- x/bank/bench_test.go | 6 +- x/bank/keeper/genesis.go | 4 +- x/bank/keeper/genesis_test.go | 32 ++-- x/bank/keeper/grpc_query_test.go | 16 +- x/bank/keeper/keeper.go | 21 +-- x/bank/keeper/keeper_test.go | 176 ++++++++---------- x/bank/keeper/querier_test.go | 17 +- x/bank/keeper/send.go | 36 ++-- x/bank/simulation/operations_test.go | 3 +- x/bank/spec/02_keepers.md | 6 - x/crisis/handler_test.go | 9 +- x/distribution/keeper/allocation_test.go | 8 +- x/distribution/keeper/delegation_test.go | 7 +- x/distribution/keeper/genesis.go | 7 +- x/distribution/keeper/grpc_query_test.go | 2 +- x/distribution/keeper/keeper_test.go | 14 +- x/distribution/proposal_handler_test.go | 3 +- x/distribution/simulation/operations_test.go | 8 +- x/distribution/types/expected_keepers.go | 1 - x/evidence/keeper/keeper_test.go | 8 +- x/feegrant/ante/fee_test.go | 14 +- x/feegrant/simulation/operations_test.go | 8 +- x/genutil/gentx_test.go | 4 +- x/gov/genesis.go | 14 +- x/gov/genesis_test.go | 22 +++ x/gov/simulation/operations_test.go | 3 +- x/gov/types/expected_keepers.go | 1 - .../transfer/keeper/mbt_relay_test.go | 16 -- .../transfer/keeper/relay_test.go | 14 +- x/slashing/simulation/operations_test.go | 3 +- x/slashing/types/expected_keepers.go | 1 - x/staking/genesis.go | 26 ++- x/staking/genesis_test.go | 131 ++++++++++--- x/staking/handler_test.go | 7 +- x/staking/keeper/delegation_test.go | 95 +++------- x/staking/keeper/slash_test.go | 23 +-- x/staking/keeper/validator_test.go | 45 ++--- x/staking/simulation/operations_test.go | 3 +- x/staking/types/expected_keepers.go | 1 - 52 files changed, 553 insertions(+), 501 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 368cdd90a88f..3d3afda47ee5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### API Breaking Changes +* (x/bank) [\#8473](https://github.com/cosmos/cosmos-sdk/pull/8473) Bank keeper does not expose unsafe balance changing methods such as `SetBalance`, `SetSupply` etc. +* (x/staking) [\#8473](https://github.com/cosmos/cosmos-sdk/pull/8473) On genesis init, if non bonded pool and bonded pool balance, coming from the bank module, does not match what is saved in the staking state, the initialization will panic. +* (x/gov) [\#8473](https://github.com/cosmos/cosmos-sdk/pull/8473) On genesis init, if the gov module account balance, coming from bank module state, does not match the one in gov module state, the initialization will panic. +* (x/distribution) [\#8473](https://github.com/cosmos/cosmos-sdk/pull/8473) On genesis init, if the distribution module account balance, coming from bank module state, does not match the one in distribution module state, the initialization will panic. * (client/keys) [\#8500](https://github.com/cosmos/cosmos-sdk/pull/8500) `InfoImporter` interface is removed from legacy keybase. ### State Machine Breaking @@ -54,7 +58,6 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements - ### Bug Fixes * (x/evidence) [#8461](https://github.com/cosmos/cosmos-sdk/pull/8461) Fix bech32 prefix in evidence validator address conversion diff --git a/simapp/state.go b/simapp/state.go index 4c3773813a04..e90bb0257ca0 100644 --- a/simapp/state.go +++ b/simapp/state.go @@ -14,9 +14,12 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" simappparams "github.com/cosmos/cosmos-sdk/simapp/params" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) // AppStateFn returns the initial application state using a genesis or the simulation parameters. @@ -68,6 +71,57 @@ func AppStateFn(cdc codec.JSONMarshaler, simManager *module.SimulationManager) s appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams) } + rawState := make(map[string]json.RawMessage) + err := json.Unmarshal(appState, &rawState) + if err != nil { + panic(err) + } + + stakingStateBz, ok := rawState[stakingtypes.ModuleName] + if !ok { + panic("staking genesis state is missing") + } + + stakingState := new(stakingtypes.GenesisState) + err = cdc.UnmarshalJSON(stakingStateBz, stakingState) + if err != nil { + panic(err) + } + // compute not bonded balance + notBondedTokens := sdk.ZeroInt() + for _, val := range stakingState.Validators { + if val.Status != stakingtypes.Unbonded { + continue + } + notBondedTokens = notBondedTokens.Add(val.GetTokens()) + } + notBondedCoins := sdk.NewCoin(stakingState.Params.BondDenom, notBondedTokens) + // edit bank state to make it have the not bonded pool tokens + bankStateBz, ok := rawState[banktypes.ModuleName] + // TODO(fdymylja/jonathan): should we panic in this case + if !ok { + panic("bank genesis state is missing") + } + bankState := new(banktypes.GenesisState) + err = cdc.UnmarshalJSON(bankStateBz, bankState) + if err != nil { + panic(err) + } + + bankState.Balances = append(bankState.Balances, banktypes.Balance{ + Address: authtypes.NewModuleAddress(stakingtypes.NotBondedPoolName).String(), + Coins: sdk.NewCoins(notBondedCoins), + }) + + // change appState back + rawState[stakingtypes.ModuleName] = cdc.MustMarshalJSON(stakingState) + rawState[banktypes.ModuleName] = cdc.MustMarshalJSON(bankState) + + // replace appstate + appState, err = json.Marshal(rawState) + if err != nil { + panic(err) + } return appState, simAccs, chainID, genesisTimestamp } } diff --git a/simapp/test_helpers.go b/simapp/test_helpers.go index 83f2ea45351f..9df0fdb75434 100644 --- a/simapp/test_helpers.go +++ b/simapp/test_helpers.go @@ -27,6 +27,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/errors" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -119,7 +120,6 @@ func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec())) } - // set validators and delegations stakingGenesis := stakingtypes.NewGenesisState(stakingtypes.DefaultParams(), validators, delegations) genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGenesis) @@ -130,6 +130,12 @@ func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs totalSupply = totalSupply.Add(b.Coins.Add(sdk.NewCoin(sdk.DefaultBondDenom, bondAmt))...) } + // add bonded amount to bonded pool module account + balances = append(balances, banktypes.Balance{ + Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(), + Coins: sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)}, + }) + // update total supply bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{}) genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis) @@ -231,21 +237,11 @@ func createIncrementalAccounts(accNum int) []sdk.AccAddress { func AddTestAddrsFromPubKeys(app *SimApp, ctx sdk.Context, pubKeys []cryptotypes.PubKey, accAmt sdk.Int) { initCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), accAmt)) - setTotalSupply(app, ctx, accAmt, len(pubKeys)) - - // fill all the addresses with some coins, set the loose pool tokens simultaneously - for _, pubKey := range pubKeys { - saveAccount(app, ctx, sdk.AccAddress(pubKey.Address()), initCoins) + for _, pk := range pubKeys { + initAccountWithCoins(app, ctx, sdk.AccAddress(pk.Address()), initCoins) } } -// setTotalSupply provides the total supply based on accAmt * totalAccounts. -func setTotalSupply(app *SimApp, ctx sdk.Context, accAmt sdk.Int, totalAccounts int) { - totalSupply := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), accAmt.MulRaw(int64(totalAccounts)))) - prevSupply := app.BankKeeper.GetSupply(ctx) - app.BankKeeper.SetSupply(ctx, banktypes.NewSupply(prevSupply.GetTotal().Add(totalSupply...))) -} - // AddTestAddrs constructs and returns accNum amount of accounts with an // initial balance of accAmt in random order func AddTestAddrs(app *SimApp, ctx sdk.Context, accNum int, accAmt sdk.Int) []sdk.AccAddress { @@ -262,21 +258,21 @@ func addTestAddrs(app *SimApp, ctx sdk.Context, accNum int, accAmt sdk.Int, stra testAddrs := strategy(accNum) initCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), accAmt)) - setTotalSupply(app, ctx, accAmt, accNum) - // fill all the addresses with some coins, set the loose pool tokens simultaneously for _, addr := range testAddrs { - saveAccount(app, ctx, addr, initCoins) + initAccountWithCoins(app, ctx, addr, initCoins) } return testAddrs } -// saveAccount saves the provided account into the simapp with balance based on initCoins. -func saveAccount(app *SimApp, ctx sdk.Context, addr sdk.AccAddress, initCoins sdk.Coins) { - acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr) - app.AccountKeeper.SetAccount(ctx, acc) - err := app.BankKeeper.AddCoins(ctx, addr, initCoins) +func initAccountWithCoins(app *SimApp, ctx sdk.Context, addr sdk.AccAddress, coins sdk.Coins) { + err := app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, coins) + if err != nil { + panic(err) + } + + err = app.BankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, coins) if err != nil { panic(err) } @@ -440,3 +436,13 @@ type EmptyAppOptions struct{} func (ao EmptyAppOptions) Get(o string) interface{} { return nil } + +// FundAccount is a utility function that funds an account by minting and sending the coins to the address +// TODO(fdymylja): instead of using the mint module account, which has the permission of minting, create a "faucet" account +func FundAccount(app *SimApp, ctx sdk.Context, addr sdk.AccAddress, amounts sdk.Coins) error { + err := app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, amounts) + if err != nil { + return err + } + return app.BankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, amounts) +} diff --git a/types/query/filtered_pagination_test.go b/types/query/filtered_pagination_test.go index e0685fbaf3b8..1ba2da21d701 100644 --- a/types/query/filtered_pagination_test.go +++ b/types/query/filtered_pagination_test.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/address" @@ -27,10 +28,11 @@ func (s *paginationTestSuite) TestFilteredPaginations() { balances = append(balances, sdk.NewInt64Coin(denom, 250)) } + balances = balances.Sort() addr1 := sdk.AccAddress([]byte("addr1")) acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) - s.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, balances)) + s.Require().NoError(simapp.FundAccount(app, ctx, addr1, balances)) store := ctx.KVStore(app.GetKey(types.StoreKey)) // verify pagination with limit > total values @@ -100,10 +102,12 @@ func ExampleFilteredPaginate() { denom := fmt.Sprintf("test%ddenom", i) balances = append(balances, sdk.NewInt64Coin(denom, 250)) } + + balances = balances.Sort() addr1 := sdk.AccAddress([]byte("addr1")) acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) - err := app.BankKeeper.SetBalances(ctx, addr1, balances) + err := simapp.FundAccount(app, ctx, addr1, balances) if err != nil { // should return no error fmt.Println(err) } diff --git a/types/query/pagination_test.go b/types/query/pagination_test.go index 74a7c959e4a2..bd9dc0af13e1 100644 --- a/types/query/pagination_test.go +++ b/types/query/pagination_test.go @@ -73,10 +73,11 @@ func (s *paginationTestSuite) TestPagination() { balances = append(balances, sdk.NewInt64Coin(denom, 100)) } + balances = balances.Sort() addr1 := sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()) acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) - s.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, balances)) + s.Require().NoError(simapp.FundAccount(app, ctx, addr1, balances)) s.T().Log("verify empty page request results a max of defaultLimit records and counts total records") pageReq := &query.PageRequest{} @@ -178,11 +179,12 @@ func ExamplePaginate() { balances = append(balances, sdk.NewInt64Coin(denom, 100)) } + balances = balances.Sort() addr1 := sdk.AccAddress([]byte("addr1")) acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) - err := app.BankKeeper.SetBalances(ctx, addr1, balances) - if err != nil { + err := simapp.FundAccount(app, ctx, addr1, balances) + if err != nil { // should return no error fmt.Println(err) } // Paginate example diff --git a/x/auth/ante/ante_test.go b/x/auth/ante/ante_test.go index 7659f3e1043d..9b268b1ec60d 100644 --- a/x/auth/ante/ante_test.go +++ b/x/auth/ante/ante_test.go @@ -7,6 +7,10 @@ import ( "strings" "testing" + "github.com/cosmos/cosmos-sdk/simapp" + + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" @@ -23,7 +27,7 @@ import ( // Test that simulate transaction accurately estimates gas cost func (suite *AnteTestSuite) TestSimulateGasCost() { - suite.SetupTest(true) // reset + suite.SetupTest(false) // reset // Same data for every test cases accounts := suite.CreateTestAccounts(3) @@ -76,7 +80,7 @@ func (suite *AnteTestSuite) TestSimulateGasCost() { // Test various error cases in the AnteHandler control flow. func (suite *AnteTestSuite) TestAnteHandlerSigErrors() { - suite.SetupTest(true) // reset + suite.SetupTest(false) // reset // Same data for every test cases priv0, _, addr0 := testdata.KeyTestPubAddr() @@ -137,7 +141,9 @@ func (suite *AnteTestSuite) TestAnteHandlerSigErrors() { func() { acc1 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr0) suite.app.AccountKeeper.SetAccount(suite.ctx, acc1) - err := suite.app.BankKeeper.SetBalances(suite.ctx, addr0, feeAmount) + err := suite.app.BankKeeper.MintCoins(suite.ctx, minttypes.ModuleName, feeAmount) + suite.Require().NoError(err) + err = suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, minttypes.ModuleName, addr0, feeAmount) suite.Require().NoError(err) }, false, @@ -435,7 +441,7 @@ func (suite *AnteTestSuite) TestAnteHandlerSequences() { // Test logic around fee deduction. func (suite *AnteTestSuite) TestAnteHandlerFees() { - suite.SetupTest(true) // setup + suite.SetupTest(false) // setup // Same data for every test cases priv0, _, addr0 := testdata.KeyTestPubAddr() @@ -466,7 +472,8 @@ func (suite *AnteTestSuite) TestAnteHandlerFees() { { "signer does not have enough funds to pay the fee", func() { - suite.app.BankKeeper.SetBalances(suite.ctx, addr0, sdk.NewCoins(sdk.NewInt64Coin("atom", 149))) + err := simapp.FundAccount(suite.app, suite.ctx, addr0, sdk.NewCoins(sdk.NewInt64Coin("atom", 149))) + suite.Require().NoError(err) }, false, false, @@ -475,12 +482,14 @@ func (suite *AnteTestSuite) TestAnteHandlerFees() { { "signer as enough funds, should pass", func() { + accNums = []uint64{7} modAcc := suite.app.AccountKeeper.GetModuleAccount(suite.ctx, types.FeeCollectorName) suite.Require().True(suite.app.BankKeeper.GetAllBalances(suite.ctx, modAcc.GetAddress()).Empty()) require.True(sdk.IntEq(suite.T(), suite.app.BankKeeper.GetAllBalances(suite.ctx, addr0).AmountOf("atom"), sdk.NewInt(149))) - suite.app.BankKeeper.SetBalances(suite.ctx, addr0, sdk.NewCoins(sdk.NewInt64Coin("atom", 150))) + err := simapp.FundAccount(suite.app, suite.ctx, addr0, sdk.NewCoins(sdk.NewInt64Coin("atom", 1))) + suite.Require().NoError(err) }, false, true, @@ -960,7 +969,7 @@ func TestCountSubkeys(t *testing.T) { } func (suite *AnteTestSuite) TestAnteHandlerSigLimitExceeded() { - suite.SetupTest(true) // setup + suite.SetupTest(false) // setup // Same data for every test cases accounts := suite.CreateTestAccounts(8) @@ -997,7 +1006,7 @@ func (suite *AnteTestSuite) TestAnteHandlerSigLimitExceeded() { // Test custom SignatureVerificationGasConsumer func (suite *AnteTestSuite) TestCustomSignatureVerificationGasConsumer() { - suite.SetupTest(true) // setup + suite.SetupTest(false) // setup // setup an ante handler that only accepts PubKeyEd25519 suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.BankKeeper, func(meter sdk.GasMeter, sig signing.SignatureV2, params types.Params) error { @@ -1047,7 +1056,7 @@ func (suite *AnteTestSuite) TestCustomSignatureVerificationGasConsumer() { } func (suite *AnteTestSuite) TestAnteHandlerReCheck() { - suite.SetupTest(true) // setup + suite.SetupTest(false) // setup // Set recheck=true suite.ctx = suite.ctx.WithIsReCheckTx(true) suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder() @@ -1120,7 +1129,9 @@ func (suite *AnteTestSuite) TestAnteHandlerReCheck() { // remove funds for account so antehandler fails on recheck suite.app.AccountKeeper.SetAccount(suite.ctx, accounts[0].acc) - suite.app.BankKeeper.SetBalances(suite.ctx, accounts[0].acc.GetAddress(), sdk.NewCoins()) + balances := suite.app.BankKeeper.GetAllBalances(suite.ctx, accounts[0].acc.GetAddress()) + err = suite.app.BankKeeper.SendCoinsFromAccountToModule(suite.ctx, accounts[0].acc.GetAddress(), minttypes.ModuleName, balances) + suite.Require().NoError(err) _, err = suite.anteHandler(suite.ctx, tx, false) suite.Require().NotNil(err, "antehandler on recheck did not fail once feePayer no longer has sufficient funds") diff --git a/x/auth/ante/fee_test.go b/x/auth/ante/fee_test.go index 84e5adb60db7..343e814583d2 100644 --- a/x/auth/ante/fee_test.go +++ b/x/auth/ante/fee_test.go @@ -2,8 +2,8 @@ package ante_test import ( cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/testutil/testdata" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/ante" ) @@ -61,7 +61,7 @@ func (suite *AnteTestSuite) TestEnsureMempoolFees() { } func (suite *AnteTestSuite) TestDeductFees() { - suite.SetupTest(true) // setup + suite.SetupTest(false) // setup suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder() // keys and addresses @@ -82,7 +82,9 @@ func (suite *AnteTestSuite) TestDeductFees() { // Set account with insufficient funds acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) - suite.app.BankKeeper.SetBalances(suite.ctx, addr1, sdk.NewCoins(sdk.NewCoin("atom", sdk.NewInt(10)))) + coins := sdk.NewCoins(sdk.NewCoin("atom", sdk.NewInt(10))) + err = simapp.FundAccount(suite.app, suite.ctx, addr1, coins) + suite.Require().NoError(err) dfd := ante.NewDeductFeeDecorator(suite.app.AccountKeeper, suite.app.BankKeeper) antehandler := sdk.ChainAnteDecorators(dfd) @@ -93,7 +95,8 @@ func (suite *AnteTestSuite) TestDeductFees() { // Set account with sufficient funds suite.app.AccountKeeper.SetAccount(suite.ctx, acc) - suite.app.BankKeeper.SetBalances(suite.ctx, addr1, sdk.NewCoins(sdk.NewCoin("atom", sdk.NewInt(200)))) + err = simapp.FundAccount(suite.app, suite.ctx, addr1, sdk.NewCoins(sdk.NewCoin("atom", sdk.NewInt(200)))) + suite.Require().NoError(err) _, err = antehandler(suite.ctx, tx, false) diff --git a/x/auth/ante/testutil_test.go b/x/auth/ante/testutil_test.go index 5a1cfc4ec44c..78af9743eadd 100644 --- a/x/auth/ante/testutil_test.go +++ b/x/auth/ante/testutil_test.go @@ -5,6 +5,8 @@ import ( "fmt" "testing" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + "github.com/stretchr/testify/suite" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -75,9 +77,14 @@ func (suite *AnteTestSuite) CreateTestAccounts(numAccs int) []TestAccount { err := acc.SetAccountNumber(uint64(i)) suite.Require().NoError(err) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) - suite.app.BankKeeper.SetBalances(suite.ctx, addr, sdk.Coins{ + someCoins := sdk.Coins{ sdk.NewInt64Coin("atom", 10000000), - }) + } + err = suite.app.BankKeeper.MintCoins(suite.ctx, minttypes.ModuleName, someCoins) + suite.Require().NoError(err) + + err = suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, minttypes.ModuleName, addr, someCoins) + suite.Require().NoError(err) accounts = append(accounts, TestAccount{acc, priv}) } diff --git a/x/auth/signing/verify_test.go b/x/auth/signing/verify_test.go index 7e842d13537c..22cd3eb2754f 100644 --- a/x/auth/signing/verify_test.go +++ b/x/auth/signing/verify_test.go @@ -40,9 +40,9 @@ func TestVerifySignature(t *testing.T) { _ = app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) balances := sdk.NewCoins(sdk.NewInt64Coin("atom", 200)) - require.NoError(t, app.BankKeeper.SetBalances(ctx, addr, balances)) + require.NoError(t, simapp.FundAccount(app, ctx, addr, balances)) acc, err := ante.GetSignerAcc(ctx, app.AccountKeeper, addr) - require.NoError(t, app.BankKeeper.SetBalances(ctx, addr, balances)) + require.NoError(t, simapp.FundAccount(app, ctx, addr, balances)) msgs := []sdk.Msg{testdata.NewTestMsg(addr)} fee := legacytx.NewStdFee(50000, sdk.Coins{sdk.NewInt64Coin("atom", 150)}) diff --git a/x/auth/vesting/handler_test.go b/x/auth/vesting/handler_test.go index 490fc59971f1..48be156b83a8 100644 --- a/x/auth/vesting/handler_test.go +++ b/x/auth/vesting/handler_test.go @@ -37,7 +37,7 @@ func (suite *HandlerTestSuite) TestMsgCreateVestingAccount() { acc1 := suite.app.AccountKeeper.NewAccountWithAddress(ctx, addr1) suite.app.AccountKeeper.SetAccount(ctx, acc1) - suite.Require().NoError(suite.app.BankKeeper.SetBalances(ctx, addr1, balances)) + suite.Require().NoError(simapp.FundAccount(suite.app, ctx, addr1, balances)) testCases := []struct { name string diff --git a/x/authz/keeper/keeper_test.go b/x/authz/keeper/keeper_test.go index 43dbc3b94b5f..3d53ac8ce4da 100644 --- a/x/authz/keeper/keeper_test.go +++ b/x/authz/keeper/keeper_test.go @@ -5,11 +5,14 @@ import ( "time" proto "github.com/gogo/protobuf/proto" - "github.com/stretchr/testify/suite" + + "github.com/cosmos/cosmos-sdk/baseapp" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmtime "github.com/tendermint/tendermint/types/time" - "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/stretchr/testify/suite" + "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/authz/types" @@ -48,9 +51,6 @@ func (s *TestSuite) TestKeeper() { granterAddr := addrs[0] granteeAddr := addrs[1] recipientAddr := addrs[2] - err := app.BankKeeper.SetBalances(ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000))) - s.Require().Nil(err) - s.Require().True(app.BankKeeper.GetBalance(ctx, granterAddr, "steak").IsEqual(sdk.NewCoin("steak", sdk.NewInt(10000)))) s.T().Log("verify that no authorization returns nil") authorization, expiration := app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) @@ -62,7 +62,7 @@ func (s *TestSuite) TestKeeper() { newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) s.T().Log("verify if expired authorization is rejected") x := &types.SendAuthorization{SpendLimit: newCoins} - err = app.AuthzKeeper.Grant(ctx, granterAddr, granteeAddr, x, now.Add(-1*time.Hour)) + err := app.AuthzKeeper.Grant(ctx, granterAddr, granteeAddr, x, now.Add(-1*time.Hour)) s.Require().NoError(err) authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) s.Require().Nil(authorization) @@ -103,10 +103,6 @@ func (s *TestSuite) TestKeeperIter() { granterAddr := addrs[0] granteeAddr := addrs[1] - err := app.BankKeeper.SetBalances(ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000))) - s.Require().Nil(err) - s.Require().True(app.BankKeeper.GetBalance(ctx, granterAddr, "steak").IsEqual(sdk.NewCoin("steak", sdk.NewInt(10000)))) - s.T().Log("verify that no authorization returns nil") authorization, expiration := app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, "Abcd") s.Require().Nil(authorization) @@ -117,7 +113,7 @@ func (s *TestSuite) TestKeeperIter() { newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) s.T().Log("verify if expired authorization is rejected") x := &types.SendAuthorization{SpendLimit: newCoins} - err = app.AuthzKeeper.Grant(ctx, granteeAddr, granterAddr, x, now.Add(-1*time.Hour)) + err := app.AuthzKeeper.Grant(ctx, granteeAddr, granterAddr, x, now.Add(-1*time.Hour)) s.Require().NoError(err) authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, "abcd") s.Require().Nil(authorization) @@ -136,10 +132,7 @@ func (s *TestSuite) TestKeeperFees() { granterAddr := addrs[0] granteeAddr := addrs[1] recipientAddr := addrs[2] - err := app.BankKeeper.SetBalances(s.ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000))) - s.Require().Nil(err) - s.Require().True(app.BankKeeper.GetBalance(s.ctx, granterAddr, "steak").IsEqual(sdk.NewCoin("steak", sdk.NewInt(10000)))) - + s.Require().NoError(simapp.FundAccount(app, s.ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000)))) now := s.ctx.BlockHeader().Time s.Require().NotNil(now) @@ -180,8 +173,8 @@ func (s *TestSuite) TestKeeperFees() { s.Require().NoError(err) result, err = app.AuthzKeeper.DispatchActions(s.ctx, granteeAddr, executeMsgs) + s.Require().NoError(err) s.Require().NotNil(result) - s.Require().Nil(err) authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(s.ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) s.Require().NotNil(authorization) diff --git a/x/authz/simulation/operations_test.go b/x/authz/simulation/operations_test.go index 83be182df746..b3b447dcdb09 100644 --- a/x/authz/simulation/operations_test.go +++ b/x/authz/simulation/operations_test.go @@ -79,8 +79,7 @@ func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Ac for _, account := range accounts { acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, account.Address) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) - err := suite.app.BankKeeper.SetBalances(suite.ctx, account.Address, initCoins) - suite.Require().NoError(err) + suite.Require().NoError(simapp.FundAccount(suite.app, suite.ctx, account.Address, initCoins)) } return accounts diff --git a/x/bank/app_test.go b/x/bank/app_test.go index 82d898b09088..6cb3655cc829 100644 --- a/x/bank/app_test.go +++ b/x/bank/app_test.go @@ -95,8 +95,7 @@ func TestSendNotEnoughBalance(t *testing.T) { app := simapp.SetupWithGenesisAccounts(genAccs) ctx := app.BaseApp.NewContext(false, tmproto.Header{}) - err := app.BankKeeper.SetBalances(ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 67))) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 67)))) app.Commit() @@ -110,7 +109,7 @@ func TestSendNotEnoughBalance(t *testing.T) { sendMsg := types.NewMsgSend(addr1, addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 100)}) header := tmproto.Header{Height: app.LastBlockHeight() + 1} txGen := simapp.MakeTestEncodingConfig().TxConfig - _, _, err = simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{sendMsg}, "", []uint64{origAccNum}, []uint64{origSeq}, false, false, priv1) + _, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{sendMsg}, "", []uint64{origAccNum}, []uint64{origSeq}, false, false, priv1) require.Error(t, err) simapp.CheckBalance(t, app, addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 67)}) @@ -169,8 +168,7 @@ func TestSendToModuleAcc(t *testing.T) { toAddr, err := sdk.AccAddressFromBech32(test.msg.ToAddress) require.NoError(t, err) - err = app.BankKeeper.SetBalances(ctx, fromAddr, test.fromBalance) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, fromAddr, test.fromBalance)) app.Commit() @@ -211,8 +209,7 @@ func TestMsgMultiSendWithAccounts(t *testing.T) { app := simapp.SetupWithGenesisAccounts(genAccs) ctx := app.BaseApp.NewContext(false, tmproto.Header{}) - err := app.BankKeeper.SetBalances(ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 67))) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 67)))) app.Commit() @@ -282,11 +279,9 @@ func TestMsgMultiSendMultipleOut(t *testing.T) { app := simapp.SetupWithGenesisAccounts(genAccs) ctx := app.BaseApp.NewContext(false, tmproto.Header{}) - err := app.BankKeeper.SetBalances(ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42))) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) - err = app.BankKeeper.SetBalances(ctx, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42))) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) app.Commit() @@ -333,14 +328,11 @@ func TestMsgMultiSendMultipleInOut(t *testing.T) { app := simapp.SetupWithGenesisAccounts(genAccs) ctx := app.BaseApp.NewContext(false, tmproto.Header{}) - err := app.BankKeeper.SetBalances(ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42))) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) - err = app.BankKeeper.SetBalances(ctx, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42))) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) - err = app.BankKeeper.SetBalances(ctx, addr4, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42))) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, addr4, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) app.Commit() @@ -383,8 +375,7 @@ func TestMsgMultiSendDependent(t *testing.T) { app := simapp.SetupWithGenesisAccounts(genAccs) ctx := app.BaseApp.NewContext(false, tmproto.Header{}) - err = app.BankKeeper.SetBalances(ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42))) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) app.Commit() diff --git a/x/bank/bench_test.go b/x/bank/bench_test.go index 0648b3b62725..c7da72c199dd 100644 --- a/x/bank/bench_test.go +++ b/x/bank/bench_test.go @@ -30,8 +30,7 @@ func BenchmarkOneBankSendTxPerBlock(b *testing.B) { ctx := benchmarkApp.BaseApp.NewContext(false, tmproto.Header{}) // some value conceivably higher than the benchmarks would ever go - err := benchmarkApp.BankKeeper.SetBalances(ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 100000000000))) - require.NoError(b, err) + require.NoError(b, simapp.FundAccount(benchmarkApp, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 100000000000)))) benchmarkApp.Commit() txGen := simappparams.MakeTestEncodingConfig().TxConfig @@ -72,8 +71,7 @@ func BenchmarkOneBankMultiSendTxPerBlock(b *testing.B) { ctx := benchmarkApp.BaseApp.NewContext(false, tmproto.Header{}) // some value conceivably higher than the benchmarks would ever go - err := benchmarkApp.BankKeeper.SetBalances(ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 100000000000))) - require.NoError(b, err) + require.NoError(b, simapp.FundAccount(benchmarkApp, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 100000000000)))) benchmarkApp.Commit() txGen := simappparams.MakeTestEncodingConfig().TxConfig diff --git a/x/bank/keeper/genesis.go b/x/bank/keeper/genesis.go index d30415c6a285..2781645c4e5c 100644 --- a/x/bank/keeper/genesis.go +++ b/x/bank/keeper/genesis.go @@ -20,7 +20,7 @@ func (k BaseKeeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) { panic(err) } - if err := k.SetBalances(ctx, addr, balance.Coins); err != nil { + if err := k.setBalances(ctx, addr, balance.Coins); err != nil { panic(fmt.Errorf("error on setting balances %w", err)) } @@ -31,7 +31,7 @@ func (k BaseKeeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) { genState.Supply = totalSupply } - k.SetSupply(ctx, types.NewSupply(genState.Supply)) + k.setSupply(ctx, types.NewSupply(genState.Supply)) for _, meta := range genState.DenomMetadata { k.SetDenomMetaData(ctx, meta) diff --git a/x/bank/keeper/genesis_test.go b/x/bank/keeper/genesis_test.go index 0e66da54e94d..7bf7dc920315 100644 --- a/x/bank/keeper/genesis_test.go +++ b/x/bank/keeper/genesis_test.go @@ -3,43 +3,53 @@ package keeper_test import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/bank/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) func (suite *IntegrationTestSuite) TestExportGenesis() { app, ctx := suite.app, suite.ctx expectedMetadata := suite.getTestMetadata() - expectedBalances := suite.getTestBalances() + expectedBalances, totalSupply := suite.getTestBalancesAndSupply() for i := range []int{1, 2} { app.BankKeeper.SetDenomMetaData(ctx, expectedMetadata[i]) accAddr, err1 := sdk.AccAddressFromBech32(expectedBalances[i].Address) if err1 != nil { panic(err1) } - err := app.BankKeeper.SetBalances(ctx, accAddr, expectedBalances[i].Coins) - suite.Require().NoError(err) + // set balances via mint and send + suite. + Require(). + NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, expectedBalances[i].Coins)) + suite. + Require(). + NoError(app.BankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, accAddr, expectedBalances[i].Coins)) } - - totalSupply := types.NewSupply(sdk.NewCoins(sdk.NewInt64Coin("test", 400000000))) - app.BankKeeper.SetSupply(ctx, totalSupply) + // add mint module balance as nil + expectedBalances = append(expectedBalances, types.Balance{Address: "cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q", Coins: nil}) app.BankKeeper.SetParams(ctx, types.DefaultParams()) exportGenesis := app.BankKeeper.ExportGenesis(ctx) suite.Require().Len(exportGenesis.Params.SendEnabled, 0) suite.Require().Equal(types.DefaultParams().DefaultSendEnabled, exportGenesis.Params.DefaultSendEnabled) - suite.Require().Equal(totalSupply.GetTotal(), exportGenesis.Supply) + suite.Require().Equal(totalSupply.Total, exportGenesis.Supply) suite.Require().Equal(expectedBalances, exportGenesis.Balances) suite.Require().Equal(expectedMetadata, exportGenesis.DenomMetadata) } -func (suite *IntegrationTestSuite) getTestBalances() []types.Balance { +func (suite *IntegrationTestSuite) getTestBalancesAndSupply() ([]types.Balance, *types.Supply) { addr2, _ := sdk.AccAddressFromBech32("cosmos1f9xjhxm0plzrh9cskf4qee4pc2xwp0n0556gh0") addr1, _ := sdk.AccAddressFromBech32("cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh") + addr1Balance := sdk.Coins{sdk.NewInt64Coin("testcoin3", 10)} + addr2Balance := sdk.Coins{sdk.NewInt64Coin("testcoin1", 32), sdk.NewInt64Coin("testcoin2", 34)} + + totalSupply := types.NewSupply(addr1Balance) + totalSupply.Inflate(addr2Balance) return []types.Balance{ - {Address: addr2.String(), Coins: sdk.Coins{sdk.NewInt64Coin("testcoin1", 32), sdk.NewInt64Coin("testcoin2", 34)}}, - {Address: addr1.String(), Coins: sdk.Coins{sdk.NewInt64Coin("testcoin3", 10)}}, - } + {Address: addr2.String(), Coins: addr2Balance}, + {Address: addr1.String(), Coins: addr1Balance}, + }, totalSupply } diff --git a/x/bank/keeper/grpc_query_test.go b/x/bank/keeper/grpc_query_test.go index e178f1301751..cd319b247b0d 100644 --- a/x/bank/keeper/grpc_query_test.go +++ b/x/bank/keeper/grpc_query_test.go @@ -6,6 +6,10 @@ import ( gocontext "context" "fmt" + "github.com/cosmos/cosmos-sdk/simapp" + + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" @@ -32,7 +36,7 @@ func (suite *IntegrationTestSuite) TestQueryBalance() { acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr) app.AccountKeeper.SetAccount(ctx, acc) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, acc.GetAddress(), origCoins)) + suite.Require().NoError(simapp.FundAccount(app, ctx, acc.GetAddress(), origCoins)) res, err = queryClient.Balance(gocontext.Background(), req) suite.Require().NoError(err) @@ -64,7 +68,7 @@ func (suite *IntegrationTestSuite) TestQueryAllBalances() { acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr) app.AccountKeeper.SetAccount(ctx, acc) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, acc.GetAddress(), origCoins)) + suite.Require().NoError(simapp.FundAccount(app, ctx, acc.GetAddress(), origCoins)) res, err = queryClient.AllBalances(gocontext.Background(), req) suite.Require().NoError(err) @@ -87,7 +91,9 @@ func (suite *IntegrationTestSuite) TestQueryAllBalances() { func (suite *IntegrationTestSuite) TestQueryTotalSupply() { app, ctx, queryClient := suite.app, suite.ctx, suite.queryClient expectedTotalSupply := types.NewSupply(sdk.NewCoins(sdk.NewInt64Coin("test", 400000000))) - app.BankKeeper.SetSupply(ctx, expectedTotalSupply) + suite. + Require(). + NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, expectedTotalSupply.Total)) res, err := queryClient.TotalSupply(gocontext.Background(), &types.QueryTotalSupplyRequest{}) suite.Require().NoError(err) @@ -102,7 +108,9 @@ func (suite *IntegrationTestSuite) TestQueryTotalSupplyOf() { test1Supply := sdk.NewInt64Coin("test1", 4000000) test2Supply := sdk.NewInt64Coin("test2", 700000000) expectedTotalSupply := types.NewSupply(sdk.NewCoins(test1Supply, test2Supply)) - app.BankKeeper.SetSupply(ctx, expectedTotalSupply) + suite. + Require(). + NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, expectedTotalSupply.Total)) _, err := queryClient.SupplyOf(gocontext.Background(), &types.QuerySupplyOfRequest{}) suite.Require().Error(err) diff --git a/x/bank/keeper/keeper.go b/x/bank/keeper/keeper.go index e5f221e4e204..153d5d4a55d9 100644 --- a/x/bank/keeper/keeper.go +++ b/x/bank/keeper/keeper.go @@ -25,7 +25,6 @@ type Keeper interface { ExportGenesis(sdk.Context) *types.GenesisState GetSupply(ctx sdk.Context) exported.SupplyI - SetSupply(ctx sdk.Context, supply exported.SupplyI) GetDenomMetaData(ctx sdk.Context, denom string) (types.Metadata, bool) SetDenomMetaData(ctx sdk.Context, denomMetaData types.Metadata) @@ -102,7 +101,7 @@ func (k BaseKeeper) DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr } balances = balances.Add(balance) - err := k.SetBalance(ctx, delegatorAddr, balance.Sub(coin)) + err := k.setBalance(ctx, delegatorAddr, balance.Sub(coin)) if err != nil { return err } @@ -112,7 +111,7 @@ func (k BaseKeeper) DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr return sdkerrors.Wrap(err, "failed to track delegation") } - err := k.AddCoins(ctx, moduleAccAddr, amt) + err := k.addCoins(ctx, moduleAccAddr, amt) if err != nil { return err } @@ -135,7 +134,7 @@ func (k BaseKeeper) UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAdd return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, amt.String()) } - err := k.SubtractCoins(ctx, moduleAccAddr, amt) + err := k.subtractCoins(ctx, moduleAccAddr, amt) if err != nil { return err } @@ -144,7 +143,7 @@ func (k BaseKeeper) UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAdd return sdkerrors.Wrap(err, "failed to track undelegation") } - err = k.AddCoins(ctx, delegatorAddr, amt) + err = k.addCoins(ctx, delegatorAddr, amt) if err != nil { return err } @@ -168,8 +167,8 @@ func (k BaseKeeper) GetSupply(ctx sdk.Context) exported.SupplyI { return supply } -// SetSupply sets the Supply to store -func (k BaseKeeper) SetSupply(ctx sdk.Context, supply exported.SupplyI) { +// setSupply sets the Supply to store +func (k BaseKeeper) setSupply(ctx sdk.Context, supply exported.SupplyI) { store := ctx.KVStore(k.storeKey) bz, err := k.MarshalSupply(supply) if err != nil { @@ -332,7 +331,7 @@ func (k BaseKeeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) panic(sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to mint tokens", moduleName)) } - err := k.AddCoins(ctx, acc.GetAddress(), amt) + err := k.addCoins(ctx, acc.GetAddress(), amt) if err != nil { return err } @@ -341,7 +340,7 @@ func (k BaseKeeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) supply := k.GetSupply(ctx) supply.Inflate(amt) - k.SetSupply(ctx, supply) + k.setSupply(ctx, supply) logger := k.Logger(ctx) logger.Info("minted coins from module account", "amount", amt.String(), "from", moduleName) @@ -361,7 +360,7 @@ func (k BaseKeeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) panic(sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to burn tokens", moduleName)) } - err := k.SubtractCoins(ctx, acc.GetAddress(), amt) + err := k.subtractCoins(ctx, acc.GetAddress(), amt) if err != nil { return err } @@ -369,7 +368,7 @@ func (k BaseKeeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) // update total supply supply := k.GetSupply(ctx) supply.Deflate(amt) - k.SetSupply(ctx, supply) + k.setSupply(ctx, supply) logger := k.Logger(ctx) logger.Info("burned tokens from module account", "amount", amt.String(), "from", moduleName) diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index 80b4b070c278..20ec854a81c2 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -4,6 +4,8 @@ import ( "testing" "time" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + "github.com/stretchr/testify/suite" abci "github.com/tendermint/tendermint/abci/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -89,7 +91,7 @@ func (suite *IntegrationTestSuite) TestSupply() { initTokens := sdk.TokensFromConsensusPower(initialPower) totalSupply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens)) - app.BankKeeper.SetSupply(ctx, types.NewSupply(totalSupply)) + suite.NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, totalSupply)) total := app.BankKeeper.GetSupply(ctx).GetTotal() suite.Require().Equal(totalSupply, total) @@ -118,23 +120,30 @@ func (suite *IntegrationTestSuite) TestSupply_SendCoins() { ) baseAcc := authKeeper.NewAccountWithAddress(ctx, authtypes.NewModuleAddress("baseAcc")) - suite.Require().NoError(keeper.SetBalances(ctx, holderAcc.GetAddress(), initCoins)) - keeper.SetSupply(ctx, types.NewSupply(initCoins)) + // set initial balances + suite. + Require(). + NoError(keeper.MintCoins(ctx, minttypes.ModuleName, initCoins)) + + suite. + Require(). + NoError(keeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, holderAcc.GetAddress(), initCoins)) + authKeeper.SetModuleAccount(ctx, holderAcc) authKeeper.SetModuleAccount(ctx, burnerAcc) authKeeper.SetAccount(ctx, baseAcc) suite.Require().Panics(func() { - keeper.SendCoinsFromModuleToModule(ctx, "", holderAcc.GetName(), initCoins) // nolint:errcheck + _ = keeper.SendCoinsFromModuleToModule(ctx, "", holderAcc.GetName(), initCoins) // nolint:errcheck }) suite.Require().Panics(func() { - keeper.SendCoinsFromModuleToModule(ctx, authtypes.Burner, "", initCoins) // nolint:errcheck + _ = keeper.SendCoinsFromModuleToModule(ctx, authtypes.Burner, "", initCoins) // nolint:errcheck }) suite.Require().Panics(func() { - keeper.SendCoinsFromModuleToAccount(ctx, "", baseAcc.GetAddress(), initCoins) // nolint:errcheck + _ = keeper.SendCoinsFromModuleToAccount(ctx, "", baseAcc.GetAddress(), initCoins) // nolint:errcheck }) suite.Require().Error( @@ -234,37 +243,45 @@ func (suite *IntegrationTestSuite) TestSupply_BurnCoins() { app.GetSubspace(types.ModuleName), make(map[string]bool), ) - suite.Require().NoError(keeper.SetBalances(ctx, burnerAcc.GetAddress(), initCoins)) - keeper.SetSupply(ctx, types.NewSupply(initCoins)) + // set burnerAcc balance authKeeper.SetModuleAccount(ctx, burnerAcc) - - initialSupply := keeper.GetSupply(ctx) - initialSupply.Inflate(initCoins) - keeper.SetSupply(ctx, initialSupply) - - suite.Require().Panics(func() { keeper.BurnCoins(ctx, "", initCoins) }, "no module account") // nolint:errcheck - suite.Require().Panics(func() { keeper.BurnCoins(ctx, authtypes.Minter, initCoins) }, "invalid permission") // nolint:errcheck - suite.Require().Panics(func() { keeper.BurnCoins(ctx, randomPerm, initialSupply.GetTotal()) }, "random permission") // nolint:errcheck - err := keeper.BurnCoins(ctx, authtypes.Burner, initialSupply.GetTotal()) + suite. + Require(). + NoError(keeper.MintCoins(ctx, authtypes.Minter, initCoins)) + suite. + Require(). + NoError(keeper.SendCoinsFromModuleToAccount(ctx, authtypes.Minter, burnerAcc.GetAddress(), initCoins)) + + // inflate supply + suite. + Require(). + NoError(keeper.MintCoins(ctx, authtypes.Minter, initCoins)) + supplyAfterInflation := keeper.GetSupply(ctx) + + suite.Require().Panics(func() { keeper.BurnCoins(ctx, "", initCoins) }, "no module account") // nolint:errcheck + suite.Require().Panics(func() { keeper.BurnCoins(ctx, authtypes.Minter, initCoins) }, "invalid permission") // nolint:errcheck + suite.Require().Panics(func() { keeper.BurnCoins(ctx, randomPerm, supplyAfterInflation.GetTotal()) }, "random permission") // nolint:errcheck + err := keeper.BurnCoins(ctx, authtypes.Burner, supplyAfterInflation.GetTotal()) suite.Require().Error(err, "insufficient coins") err = keeper.BurnCoins(ctx, authtypes.Burner, initCoins) suite.Require().NoError(err) suite.Require().Equal(sdk.Coins(nil), getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner)) - suite.Require().Equal(initialSupply.GetTotal().Sub(initCoins), keeper.GetSupply(ctx).GetTotal()) + suite.Require().Equal(supplyAfterInflation.GetTotal().Sub(initCoins), keeper.GetSupply(ctx).GetTotal()) // test same functionality on module account with multiple permissions - initialSupply = keeper.GetSupply(ctx) - initialSupply.Inflate(initCoins) - keeper.SetSupply(ctx, initialSupply) + suite. + Require(). + NoError(keeper.MintCoins(ctx, authtypes.Minter, initCoins)) + supplyAfterInflation = keeper.GetSupply(ctx) - suite.Require().NoError(keeper.SetBalances(ctx, multiPermAcc.GetAddress(), initCoins)) + suite.Require().NoError(keeper.SendCoins(ctx, authtypes.NewModuleAddress(authtypes.Minter), multiPermAcc.GetAddress(), initCoins)) authKeeper.SetModuleAccount(ctx, multiPermAcc) err = keeper.BurnCoins(ctx, multiPermAcc.GetName(), initCoins) suite.Require().NoError(err) suite.Require().Equal(sdk.Coins(nil), getCoinsByName(ctx, keeper, authKeeper, multiPermAcc.GetName())) - suite.Require().Equal(initialSupply.GetTotal().Sub(initCoins), keeper.GetSupply(ctx).GetTotal()) + suite.Require().Equal(supplyAfterInflation.GetTotal().Sub(initCoins), keeper.GetSupply(ctx).GetTotal()) } func (suite *IntegrationTestSuite) TestSendCoinsNewAccount() { @@ -274,7 +291,7 @@ func (suite *IntegrationTestSuite) TestSendCoinsNewAccount() { addr1 := sdk.AccAddress([]byte("addr1_______________")) acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, balances)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, balances)) acc1Balances := app.BankKeeper.GetAllBalances(ctx, addr1) suite.Require().Equal(balances, acc1Balances) @@ -300,7 +317,7 @@ func (suite *IntegrationTestSuite) TestInputOutputNewAccount() { addr1 := sdk.AccAddress([]byte("addr1_______________")) acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, balances)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, balances)) acc1Balances := app.BankKeeper.GetAllBalances(ctx, addr1) suite.Require().Equal(balances, acc1Balances) @@ -353,7 +370,7 @@ func (suite *IntegrationTestSuite) TestInputOutputCoins() { suite.Require().Error(app.BankKeeper.InputOutputCoins(ctx, inputs, []types.Output{})) suite.Require().Error(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs)) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, balances)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, balances)) insufficientInputs := []types.Input{ {Address: addr1.String(), Coins: sdk.NewCoins(newFooCoin(300), newBarCoin(100))}, @@ -381,19 +398,19 @@ func (suite *IntegrationTestSuite) TestSendCoins() { app, ctx := suite.app, suite.ctx balances := sdk.NewCoins(newFooCoin(100), newBarCoin(50)) - addr1 := sdk.AccAddress([]byte("addr1_______________")) + addr1 := sdk.AccAddress("addr1_______________") acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) app.AccountKeeper.SetAccount(ctx, acc1) - addr2 := sdk.AccAddress([]byte("addr2_______________")) + addr2 := sdk.AccAddress("addr2_______________") acc2 := app.AccountKeeper.NewAccountWithAddress(ctx, addr2) app.AccountKeeper.SetAccount(ctx, acc2) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr2, balances)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr2, balances)) sendAmt := sdk.NewCoins(newFooCoin(50), newBarCoin(25)) suite.Require().Error(app.BankKeeper.SendCoins(ctx, addr1, addr2, sendAmt)) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, balances)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, balances)) suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr1, addr2, sendAmt)) acc1Balances := app.BankKeeper.GetAllBalances(ctx, addr1) @@ -420,45 +437,17 @@ func (suite *IntegrationTestSuite) TestValidateBalance() { app.AccountKeeper.SetAccount(ctx, acc) balances := sdk.NewCoins(newFooCoin(100)) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, balances)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, balances)) suite.Require().NoError(app.BankKeeper.ValidateBalance(ctx, addr1)) bacc := authtypes.NewBaseAccountWithAddress(addr2) vacc := vesting.NewContinuousVestingAccount(bacc, balances.Add(balances...), now.Unix(), endTime.Unix()) app.AccountKeeper.SetAccount(ctx, vacc) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr2, balances)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr2, balances)) suite.Require().Error(app.BankKeeper.ValidateBalance(ctx, addr2)) } -func (suite *IntegrationTestSuite) TestBalance() { - app, ctx := suite.app, suite.ctx - addr := sdk.AccAddress([]byte("addr1_______________")) - - acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr) - app.AccountKeeper.SetAccount(ctx, acc) - - suite.Require().Equal(sdk.NewCoin(fooDenom, sdk.ZeroInt()), app.BankKeeper.GetBalance(ctx, addr, fooDenom)) - balances := sdk.NewCoins(newFooCoin(100)) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr, balances)) - - suite.Require().Equal(balances.AmountOf(fooDenom), app.BankKeeper.GetBalance(ctx, addr, fooDenom).Amount) - suite.Require().Equal(balances, app.BankKeeper.GetAllBalances(ctx, addr)) - - newFooBalance := newFooCoin(99) - suite.Require().NoError(app.BankKeeper.SetBalance(ctx, addr, newFooBalance)) - suite.Require().Equal(newFooBalance, app.BankKeeper.GetBalance(ctx, addr, fooDenom)) - - balances = sdk.NewCoins(newBarCoin(500)) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr, balances)) - suite.Require().Equal(sdk.NewCoin(fooDenom, sdk.ZeroInt()), app.BankKeeper.GetBalance(ctx, addr, fooDenom)) - suite.Require().Equal(balances.AmountOf(barDenom), app.BankKeeper.GetBalance(ctx, addr, barDenom).Amount) - suite.Require().Equal(balances, app.BankKeeper.GetAllBalances(ctx, addr)) - - invalidBalance := sdk.Coin{Denom: "fooDenom", Amount: sdk.NewInt(-50)} - suite.Require().Error(app.BankKeeper.SetBalance(ctx, addr, invalidBalance)) -} - func (suite *IntegrationTestSuite) TestSendEnabled() { app, ctx := suite.app, suite.ctx enabled := true @@ -512,7 +501,7 @@ func (suite *IntegrationTestSuite) TestHasBalance() { balances := sdk.NewCoins(newFooCoin(100)) suite.Require().False(app.BankKeeper.HasBalance(ctx, addr, newFooCoin(99))) - app.BankKeeper.SetBalances(ctx, addr, balances) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr, balances)) suite.Require().False(app.BankKeeper.HasBalance(ctx, addr, newFooCoin(101))) suite.Require().True(app.BankKeeper.HasBalance(ctx, addr, newFooCoin(100))) suite.Require().True(app.BankKeeper.HasBalance(ctx, addr, newFooCoin(1))) @@ -560,15 +549,16 @@ func (suite *IntegrationTestSuite) TestMsgSendEvents() { suite.Require().Equal(abci.Event(event1), events[0]) suite.Require().Equal(abci.Event(event2), events[1]) - app.BankKeeper.SetBalances(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50))) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr, sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50)))) newCoins = sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50)) suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr, addr2, newCoins)) + // events are shifted due to the funding account events events = ctx.EventManager().ABCIEvents() - suite.Require().Equal(4, len(events)) - suite.Require().Equal(abci.Event(event1), events[2]) - suite.Require().Equal(abci.Event(event2), events[3]) + suite.Require().Equal(6, len(events)) + suite.Require().Equal(abci.Event(event1), events[4]) + suite.Require().Equal(abci.Event(event2), events[5]) } func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { @@ -603,12 +593,11 @@ func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { suite.Require().Equal(0, len(events)) // Set addr's coins but not addr2's coins - app.BankKeeper.SetBalances(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50))) - + suite.Require().NoError(simapp.FundAccount(app, ctx, addr, sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50)))) suite.Require().Error(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs)) events = ctx.EventManager().ABCIEvents() - suite.Require().Equal(1, len(events)) + suite.Require().Equal(3, len(events)) // 3 events because minting event is there event1 := sdk.Event{ Type: sdk.EventTypeMessage, @@ -618,19 +607,19 @@ func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { event1.Attributes, abci.EventAttribute{Key: []byte(types.AttributeKeySender), Value: []byte(addr.String())}, ) - suite.Require().Equal(abci.Event(event1), events[0]) + suite.Require().Equal(abci.Event(event1), events[2]) // it's the third event since we have the minting event before // Set addr's coins and addr2's coins - app.BankKeeper.SetBalances(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50))) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr, sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50)))) newCoins = sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50)) - app.BankKeeper.SetBalances(ctx, addr2, sdk.NewCoins(sdk.NewInt64Coin(barDenom, 100))) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr2, sdk.NewCoins(sdk.NewInt64Coin(barDenom, 100)))) newCoins2 = sdk.NewCoins(sdk.NewInt64Coin(barDenom, 100)) suite.Require().NoError(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs)) events = ctx.EventManager().ABCIEvents() - suite.Require().Equal(5, len(events)) + suite.Require().Equal(11, len(events)) event2 := sdk.Event{ Type: sdk.EventTypeMessage, @@ -664,10 +653,11 @@ func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { abci.EventAttribute{Key: []byte(sdk.AttributeKeyAmount), Value: []byte(newCoins2.String())}, ) - suite.Require().Equal(abci.Event(event1), events[1]) - suite.Require().Equal(abci.Event(event2), events[2]) - suite.Require().Equal(abci.Event(event3), events[3]) - suite.Require().Equal(abci.Event(event4), events[4]) + // events are shifted due to the funding account events + suite.Require().Equal(abci.Event(event1), events[7]) + suite.Require().Equal(abci.Event(event2), events[8]) + suite.Require().Equal(abci.Event(event3), events[9]) + suite.Require().Equal(abci.Event(event4), events[10]) } func (suite *IntegrationTestSuite) TestSpendableCoins() { @@ -691,8 +681,8 @@ func (suite *IntegrationTestSuite) TestSpendableCoins() { app.AccountKeeper.SetAccount(ctx, macc) app.AccountKeeper.SetAccount(ctx, vacc) app.AccountKeeper.SetAccount(ctx, acc) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, origCoins)) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr2, origCoins)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, origCoins)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr2, origCoins)) suite.Require().Equal(origCoins, app.BankKeeper.SpendableCoins(ctx, addr2)) @@ -717,14 +707,13 @@ func (suite *IntegrationTestSuite) TestVestingAccountSend() { vacc := vesting.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) app.AccountKeeper.SetAccount(ctx, vacc) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, origCoins)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, origCoins)) // require that no coins be sendable at the beginning of the vesting schedule suite.Require().Error(app.BankKeeper.SendCoins(ctx, addr1, addr2, sendCoins)) // receive some coins - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, origCoins.Add(sendCoins...))) - + suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, sendCoins)) // require that all vested coins are spendable plus any received ctx = ctx.WithBlockTime(now.Add(12 * time.Hour)) suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr1, addr2, sendCoins)) @@ -750,13 +739,13 @@ func (suite *IntegrationTestSuite) TestPeriodicVestingAccountSend() { vacc := vesting.NewPeriodicVestingAccount(bacc, origCoins, ctx.BlockHeader().Time.Unix(), periods) app.AccountKeeper.SetAccount(ctx, vacc) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, origCoins)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, origCoins)) // require that no coins be sendable at the beginning of the vesting schedule suite.Require().Error(app.BankKeeper.SendCoins(ctx, addr1, addr2, sendCoins)) // receive some coins - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, origCoins.Add(sendCoins...))) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, sendCoins)) // require that all vested coins are spendable plus any received ctx = ctx.WithBlockTime(now.Add(12 * time.Hour)) @@ -782,8 +771,8 @@ func (suite *IntegrationTestSuite) TestVestingAccountReceive() { app.AccountKeeper.SetAccount(ctx, vacc) app.AccountKeeper.SetAccount(ctx, acc) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, origCoins)) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr2, origCoins)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, origCoins)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr2, origCoins)) // send some coins to the vesting account suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr2, addr1, sendCoins)) @@ -821,8 +810,8 @@ func (suite *IntegrationTestSuite) TestPeriodicVestingAccountReceive() { app.AccountKeeper.SetAccount(ctx, vacc) app.AccountKeeper.SetAccount(ctx, acc) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, origCoins)) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr2, origCoins)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, origCoins)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr2, origCoins)) // send some coins to the vesting account suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr2, addr1, sendCoins)) @@ -858,8 +847,8 @@ func (suite *IntegrationTestSuite) TestDelegateCoins() { app.AccountKeeper.SetAccount(ctx, vacc) app.AccountKeeper.SetAccount(ctx, acc) app.AccountKeeper.SetAccount(ctx, macc) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, origCoins)) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr2, origCoins)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, origCoins)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr2, origCoins)) ctx = ctx.WithBlockTime(now.Add(12 * time.Hour)) @@ -889,11 +878,8 @@ func (suite *IntegrationTestSuite) TestDelegateCoins_Invalid() { suite.Require().Error(app.BankKeeper.DelegateCoins(ctx, addr1, addrModule, invalidCoins)) app.AccountKeeper.SetAccount(ctx, macc) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, origCoins)) - suite.Require().Error(app.BankKeeper.DelegateCoins(ctx, addr1, addrModule, delCoins)) app.AccountKeeper.SetAccount(ctx, acc) - suite.Require().Error(app.BankKeeper.DelegateCoins(ctx, addr1, addrModule, origCoins.Add(origCoins...))) } @@ -919,8 +905,8 @@ func (suite *IntegrationTestSuite) TestUndelegateCoins() { app.AccountKeeper.SetAccount(ctx, vacc) app.AccountKeeper.SetAccount(ctx, acc) app.AccountKeeper.SetAccount(ctx, macc) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, origCoins)) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr2, origCoins)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, origCoins)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr2, origCoins)) ctx = ctx.WithBlockTime(now.Add(12 * time.Hour)) @@ -964,7 +950,7 @@ func (suite *IntegrationTestSuite) TestUndelegateCoins_Invalid() { suite.Require().Error(app.BankKeeper.UndelegateCoins(ctx, addrModule, addr1, delCoins)) app.AccountKeeper.SetAccount(ctx, macc) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, origCoins)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, origCoins)) suite.Require().Error(app.BankKeeper.UndelegateCoins(ctx, addrModule, addr1, delCoins)) app.AccountKeeper.SetAccount(ctx, acc) diff --git a/x/bank/keeper/querier_test.go b/x/bank/keeper/querier_test.go index 84ec3d095799..ef1edc57679d 100644 --- a/x/bank/keeper/querier_test.go +++ b/x/bank/keeper/querier_test.go @@ -3,6 +3,10 @@ package keeper_test import ( "fmt" + "github.com/cosmos/cosmos-sdk/simapp" + + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + abci "github.com/tendermint/tendermint/abci/types" "github.com/cosmos/cosmos-sdk/testutil/testdata" @@ -39,7 +43,7 @@ func (suite *IntegrationTestSuite) TestQuerier_QueryBalance() { acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr) app.AccountKeeper.SetAccount(ctx, acc) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, acc.GetAddress(), origCoins)) + suite.Require().NoError(simapp.FundAccount(app, ctx, acc.GetAddress(), origCoins)) res, err = querier(ctx, []string{types.QueryBalance}, req) suite.Require().NoError(err) @@ -76,8 +80,7 @@ func (suite *IntegrationTestSuite) TestQuerier_QueryAllBalances() { acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr) app.AccountKeeper.SetAccount(ctx, acc) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, acc.GetAddress(), origCoins)) - + suite.Require().NoError(simapp.FundAccount(app, ctx, acc.GetAddress(), origCoins)) res, err = querier(ctx, []string{types.QueryAllBalances}, req) suite.Require().NoError(err) suite.Require().NotNil(res) @@ -89,7 +92,9 @@ func (suite *IntegrationTestSuite) TestQuerier_QueryTotalSupply() { app, ctx := suite.app, suite.ctx legacyAmino := app.LegacyAmino() expectedTotalSupply := types.NewSupply(sdk.NewCoins(sdk.NewInt64Coin("test", 400000000))) - app.BankKeeper.SetSupply(ctx, expectedTotalSupply) + suite. + Require(). + NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, expectedTotalSupply.Total)) req := abci.RequestQuery{ Path: fmt.Sprintf("custom/%s/%s", types.ModuleName, types.QueryTotalSupply), @@ -118,7 +123,9 @@ func (suite *IntegrationTestSuite) TestQuerier_QueryTotalSupplyOf() { test1Supply := sdk.NewInt64Coin("test1", 4000000) test2Supply := sdk.NewInt64Coin("test2", 700000000) expectedTotalSupply := types.NewSupply(sdk.NewCoins(test1Supply, test2Supply)) - app.BankKeeper.SetSupply(ctx, expectedTotalSupply) + suite. + Require(). + NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, expectedTotalSupply.Total)) req := abci.RequestQuery{ Path: fmt.Sprintf("custom/%s/%s", types.ModuleName, types.QuerySupplyOf), diff --git a/x/bank/keeper/send.go b/x/bank/keeper/send.go index 694c43211e07..c0c3a4cb62dc 100644 --- a/x/bank/keeper/send.go +++ b/x/bank/keeper/send.go @@ -17,12 +17,6 @@ type SendKeeper interface { InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) error SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error - SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) error - AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) error - - SetBalance(ctx sdk.Context, addr sdk.AccAddress, balance sdk.Coin) error - SetBalances(ctx sdk.Context, addr sdk.AccAddress, balances sdk.Coins) error - GetParams(ctx sdk.Context) types.Params SetParams(ctx sdk.Context, params types.Params) @@ -89,7 +83,7 @@ func (k BaseSendKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.Input, return err } - err = k.SubtractCoins(ctx, inAddress, in.Coins) + err = k.subtractCoins(ctx, inAddress, in.Coins) if err != nil { return err } @@ -107,7 +101,7 @@ func (k BaseSendKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.Input, if err != nil { return err } - err = k.AddCoins(ctx, outAddress, out.Coins) + err = k.addCoins(ctx, outAddress, out.Coins) if err != nil { return err } @@ -150,12 +144,12 @@ func (k BaseSendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAd ), }) - err := k.SubtractCoins(ctx, fromAddr, amt) + err := k.subtractCoins(ctx, fromAddr, amt) if err != nil { return err } - err = k.AddCoins(ctx, toAddr, amt) + err = k.addCoins(ctx, toAddr, amt) if err != nil { return err } @@ -173,9 +167,9 @@ func (k BaseSendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAd return nil } -// SubtractCoins removes amt coins the account by the given address. An error is +// subtractCoins removes amt coins the account by the given address. An error is // returned if the resulting balance is negative or the initial amount is invalid. -func (k BaseSendKeeper) SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) error { +func (k BaseSendKeeper) subtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) error { if !amt.IsValid() { return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, amt.String()) } @@ -194,7 +188,7 @@ func (k BaseSendKeeper) SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt newBalance := balance.Sub(coin) - err := k.SetBalance(ctx, addr, newBalance) + err := k.setBalance(ctx, addr, newBalance) if err != nil { return err } @@ -203,10 +197,10 @@ func (k BaseSendKeeper) SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt return nil } -// AddCoins adds amt to the account balance given by the provided address. An +// addCoins adds amt to the account balance given by the provided address. An // error is returned if the initial amount is invalid or if any resulting new // balance is negative. -func (k BaseSendKeeper) AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) error { +func (k BaseSendKeeper) addCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) error { if !amt.IsValid() { return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, amt.String()) } @@ -215,7 +209,7 @@ func (k BaseSendKeeper) AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.C balance := k.GetBalance(ctx, addr, coin.Denom) newBalance := balance.Add(coin) - err := k.SetBalance(ctx, addr, newBalance) + err := k.setBalance(ctx, addr, newBalance) if err != nil { return err } @@ -239,14 +233,14 @@ func (k BaseSendKeeper) ClearBalances(ctx sdk.Context, addr sdk.AccAddress) { } } -// SetBalances sets the balance (multiple coins) for an account by address. It will +// setBalances sets the balance (multiple coins) for an account by address. It will // clear out all balances prior to setting the new coins as to set existing balances // to zero if they don't exist in amt. An error is returned upon failure. -func (k BaseSendKeeper) SetBalances(ctx sdk.Context, addr sdk.AccAddress, balances sdk.Coins) error { +func (k BaseSendKeeper) setBalances(ctx sdk.Context, addr sdk.AccAddress, balances sdk.Coins) error { k.ClearBalances(ctx, addr) for _, balance := range balances { - err := k.SetBalance(ctx, addr, balance) + err := k.setBalance(ctx, addr, balance) if err != nil { return err } @@ -255,8 +249,8 @@ func (k BaseSendKeeper) SetBalances(ctx sdk.Context, addr sdk.AccAddress, balanc return nil } -// SetBalance sets the coin balance for an account by address. -func (k BaseSendKeeper) SetBalance(ctx sdk.Context, addr sdk.AccAddress, balance sdk.Coin) error { +// setBalance sets the coin balance for an account by address. +func (k BaseSendKeeper) setBalance(ctx sdk.Context, addr sdk.AccAddress, balance sdk.Coin) error { if !balance.IsValid() { return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, balance.String()) } diff --git a/x/bank/simulation/operations_test.go b/x/bank/simulation/operations_test.go index 144dc5dd3429..efe6de624f5d 100644 --- a/x/bank/simulation/operations_test.go +++ b/x/bank/simulation/operations_test.go @@ -131,8 +131,7 @@ func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Ac for _, account := range accounts { acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, account.Address) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) - err := suite.app.BankKeeper.SetBalances(suite.ctx, account.Address, initCoins) - suite.Require().NoError(err) + suite.Require().NoError(simapp.FundAccount(suite.app, suite.ctx, account.Address, initCoins)) } return accounts diff --git a/x/bank/spec/02_keepers.md b/x/bank/spec/02_keepers.md index 0032961b1f3b..e7e3caba545f 100644 --- a/x/bank/spec/02_keepers.md +++ b/x/bank/spec/02_keepers.md @@ -84,12 +84,6 @@ type SendKeeper interface { InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) error SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error - SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) error - AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) error - - SetBalance(ctx sdk.Context, addr sdk.AccAddress, balance sdk.Coin) error - SetBalances(ctx sdk.Context, addr sdk.AccAddress, balances sdk.Coins) error - GetParams(ctx sdk.Context) types.Params SetParams(ctx sdk.Context, params types.Params) diff --git a/x/crisis/handler_test.go b/x/crisis/handler_test.go index dcde377f6d42..593763ad82cb 100644 --- a/x/crisis/handler_test.go +++ b/x/crisis/handler_test.go @@ -5,14 +5,11 @@ import ( "testing" "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - dbm "github.com/tendermint/tm-db" "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/crisis" "github.com/cosmos/cosmos-sdk/x/crisis/types" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" @@ -26,9 +23,8 @@ var ( ) func createTestApp() (*simapp.SimApp, sdk.Context, []sdk.AccAddress) { - db := dbm.NewMemDB() - app := simapp.NewSimApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, simapp.DefaultNodeHome, 1, simapp.MakeTestEncodingConfig(), simapp.EmptyAppOptions{}) - ctx := app.NewContext(true, tmproto.Header{}) + app := simapp.Setup(false) + ctx := app.NewContext(false, tmproto.Header{}) constantFee := sdk.NewInt64Coin(sdk.DefaultBondDenom, 10) app.CrisisKeeper.SetConstantFee(ctx, constantFee) @@ -40,7 +36,6 @@ func createTestApp() (*simapp.SimApp, sdk.Context, []sdk.AccAddress) { feePool := distrtypes.InitialFeePool() feePool.CommunityPool = sdk.NewDecCoinsFromCoins(sdk.NewCoins(constantFee)...) app.DistrKeeper.SetFeePool(ctx, feePool) - app.BankKeeper.SetSupply(ctx, banktypes.NewSupply(sdk.Coins{})) addrs := simapp.AddTestAddrs(app, ctx, 1, sdk.NewInt(10000)) diff --git a/x/distribution/keeper/allocation_test.go b/x/distribution/keeper/allocation_test.go index 9d8b0012a51c..f2a33a81be51 100644 --- a/x/distribution/keeper/allocation_test.go +++ b/x/distribution/keeper/allocation_test.go @@ -82,8 +82,9 @@ func TestAllocateTokensToManyValidators(t *testing.T) { feeCollector := app.AccountKeeper.GetModuleAccount(ctx, types.FeeCollectorName) require.NotNil(t, feeCollector) - err := app.BankKeeper.SetBalances(ctx, feeCollector.GetAddress(), fees) - require.NoError(t, err) + // fund fee collector + require.NoError(t, simapp.FundAccount(app, ctx, feeCollector.GetAddress(), fees)) + app.AccountKeeper.SetAccount(ctx, feeCollector) votes := []abci.VoteInfo{ @@ -162,8 +163,7 @@ func TestAllocateTokensTruncation(t *testing.T) { feeCollector := app.AccountKeeper.GetModuleAccount(ctx, types.FeeCollectorName) require.NotNil(t, feeCollector) - err := app.BankKeeper.SetBalances(ctx, feeCollector.GetAddress(), fees) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, feeCollector.GetAddress(), fees)) app.AccountKeeper.SetAccount(ctx, feeCollector) diff --git a/x/distribution/keeper/delegation_test.go b/x/distribution/keeper/delegation_test.go index ac8ac4a33402..51def978342a 100644 --- a/x/distribution/keeper/delegation_test.go +++ b/x/distribution/keeper/delegation_test.go @@ -280,7 +280,7 @@ func TestWithdrawDelegationRewardsBasic(t *testing.T) { // set module account coins distrAcc := app.DistrKeeper.GetDistributionAccount(ctx) - require.NoError(t, app.BankKeeper.SetBalances(ctx, distrAcc.GetAddress(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, balanceTokens)))) + require.NoError(t, simapp.FundAccount(app, ctx, distrAcc.GetAddress(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, balanceTokens)))) app.AccountKeeper.SetModuleAccount(ctx, distrAcc) // create validator with 50% commission @@ -492,8 +492,7 @@ func TestCalculateRewardsMultiDelegatorMultWithdraw(t *testing.T) { // set module account coins distrAcc := app.DistrKeeper.GetDistributionAccount(ctx) - err := app.BankKeeper.SetBalances(ctx, distrAcc.GetAddress(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1000)))) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, distrAcc.GetAddress(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1000))))) app.AccountKeeper.SetModuleAccount(ctx, distrAcc) tokens := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, sdk.NewDec(initial))} @@ -538,7 +537,7 @@ func TestCalculateRewardsMultiDelegatorMultWithdraw(t *testing.T) { app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens) // first delegator withdraws - _, err = app.DistrKeeper.WithdrawDelegationRewards(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0]) + _, err := app.DistrKeeper.WithdrawDelegationRewards(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0]) require.NoError(t, err) // second delegator withdraws diff --git a/x/distribution/keeper/genesis.go b/x/distribution/keeper/genesis.go index 4aa25671a32e..5cb65d760c1e 100644 --- a/x/distribution/keeper/genesis.go +++ b/x/distribution/keeper/genesis.go @@ -97,12 +97,11 @@ func (k Keeper) InitGenesis(ctx sdk.Context, data types.GenesisState) { balances := k.bankKeeper.GetAllBalances(ctx, moduleAcc.GetAddress()) if balances.IsZero() { - if err := k.bankKeeper.SetBalances(ctx, moduleAcc.GetAddress(), moduleHoldingsInt); err != nil { - panic(err) - } - k.authKeeper.SetModuleAccount(ctx, moduleAcc) } + if !balances.IsEqual(moduleHoldingsInt) { + panic(fmt.Sprintf("distribution module balance does not match the module holdings: %s <-> %s", balances, moduleHoldingsInt)) + } } // ExportGenesis returns a GenesisState for a given context and keeper. diff --git a/x/distribution/keeper/grpc_query_test.go b/x/distribution/keeper/grpc_query_test.go index 412144094626..8beb3c715164 100644 --- a/x/distribution/keeper/grpc_query_test.go +++ b/x/distribution/keeper/grpc_query_test.go @@ -623,7 +623,7 @@ func (suite *KeeperTestSuite) TestGRPCCommunityPool() { "valid request", func() { amount := sdk.NewCoins(sdk.NewInt64Coin("stake", 100)) - suite.Require().NoError(app.BankKeeper.SetBalances(ctx, addrs[0], amount)) + suite.Require().NoError(simapp.FundAccount(app, ctx, addrs[0], amount)) err := app.DistrKeeper.FundCommunityPool(ctx, amount, addrs[0]) suite.Require().Nil(err) diff --git a/x/distribution/keeper/keeper_test.go b/x/distribution/keeper/keeper_test.go index a8205dfdc1db..ad1890225527 100644 --- a/x/distribution/keeper/keeper_test.go +++ b/x/distribution/keeper/keeper_test.go @@ -48,11 +48,9 @@ func TestWithdrawValidatorCommission(t *testing.T) { // set module account coins distrAcc := app.DistrKeeper.GetDistributionAccount(ctx) - err := app.BankKeeper.SetBalances(ctx, distrAcc.GetAddress(), sdk.NewCoins( - sdk.NewCoin("mytoken", sdk.NewInt(2)), - sdk.NewCoin("stake", sdk.NewInt(2)), - )) - require.NoError(t, err) + coins := sdk.NewCoins(sdk.NewCoin("mytoken", sdk.NewInt(2)), sdk.NewCoin("stake", sdk.NewInt(2))) + require.NoError(t, simapp.FundAccount(app, ctx, distrAcc.GetAddress(), coins)) + app.AccountKeeper.SetModuleAccount(ctx, distrAcc) // check initial balance @@ -68,7 +66,7 @@ func TestWithdrawValidatorCommission(t *testing.T) { app.DistrKeeper.SetValidatorAccumulatedCommission(ctx, valAddrs[0], types.ValidatorAccumulatedCommission{Commission: valCommission}) // withdraw commission - _, err = app.DistrKeeper.WithdrawValidatorCommission(ctx, valAddrs[0]) + _, err := app.DistrKeeper.WithdrawValidatorCommission(ctx, valAddrs[0]) require.NoError(t, err) // check balance increase @@ -113,10 +111,10 @@ func TestFundCommunityPool(t *testing.T) { app := simapp.Setup(false) ctx := app.BaseApp.NewContext(false, tmproto.Header{}) - addr := simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(1000000000)) + addr := simapp.AddTestAddrs(app, ctx, 2, sdk.ZeroInt()) amount := sdk.NewCoins(sdk.NewInt64Coin("stake", 100)) - require.NoError(t, app.BankKeeper.SetBalances(ctx, addr[0], amount)) + require.NoError(t, simapp.FundAccount(app, ctx, addr[0], amount)) initPool := app.DistrKeeper.GetFeePool(ctx) assert.Empty(t, initPool.CommunityPool) diff --git a/x/distribution/proposal_handler_test.go b/x/distribution/proposal_handler_test.go index 575dbb199cbe..c4d9bdb5c6a4 100644 --- a/x/distribution/proposal_handler_test.go +++ b/x/distribution/proposal_handler_test.go @@ -33,8 +33,7 @@ func TestProposalHandlerPassed(t *testing.T) { // add coins to the module account macc := app.DistrKeeper.GetDistributionAccount(ctx) balances := app.BankKeeper.GetAllBalances(ctx, macc.GetAddress()) - err := app.BankKeeper.SetBalances(ctx, macc.GetAddress(), balances.Add(amount...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, macc.GetAddress(), amount)) app.AccountKeeper.SetModuleAccount(ctx, macc) diff --git a/x/distribution/simulation/operations_test.go b/x/distribution/simulation/operations_test.go index 4a3dff30878e..8ac75201b174 100644 --- a/x/distribution/simulation/operations_test.go +++ b/x/distribution/simulation/operations_test.go @@ -143,11 +143,10 @@ func (suite *SimTestSuite) testSimulateMsgWithdrawValidatorCommission(tokenName // set module account coins distrAcc := suite.app.DistrKeeper.GetDistributionAccount(suite.ctx) - err := suite.app.BankKeeper.SetBalances(suite.ctx, distrAcc.GetAddress(), sdk.NewCoins( + suite.Require().NoError(simapp.FundAccount(suite.app, suite.ctx, distrAcc.GetAddress(), sdk.NewCoins( sdk.NewCoin(tokenName, sdk.NewInt(10)), sdk.NewCoin("stake", sdk.NewInt(5)), - )) - suite.Require().NoError(err) + ))) suite.app.AccountKeeper.SetModuleAccount(suite.ctx, distrAcc) // set outstanding rewards @@ -230,8 +229,7 @@ func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Ac for _, account := range accounts { acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, account.Address) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) - err := suite.app.BankKeeper.SetBalances(suite.ctx, account.Address, initCoins) - suite.Require().NoError(err) + suite.Require().NoError(simapp.FundAccount(suite.app, suite.ctx, account.Address, initCoins)) } return accounts diff --git a/x/distribution/types/expected_keepers.go b/x/distribution/types/expected_keepers.go index 29346d39081e..ac9ebc3a4eea 100644 --- a/x/distribution/types/expected_keepers.go +++ b/x/distribution/types/expected_keepers.go @@ -21,7 +21,6 @@ type AccountKeeper interface { type BankKeeper interface { GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin - SetBalances(ctx sdk.Context, addr sdk.AccAddress, balances sdk.Coins) error LockedCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins diff --git a/x/evidence/keeper/keeper_test.go b/x/evidence/keeper/keeper_test.go index 9165730466b7..6f2b071bed80 100644 --- a/x/evidence/keeper/keeper_test.go +++ b/x/evidence/keeper/keeper_test.go @@ -5,6 +5,8 @@ import ( "fmt" "time" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + "github.com/stretchr/testify/suite" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -14,7 +16,6 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/evidence/exported" "github.com/cosmos/cosmos-sdk/x/evidence/keeper" "github.com/cosmos/cosmos-sdk/x/evidence/types" @@ -130,11 +131,10 @@ func (suite *KeeperTestSuite) populateValidators(ctx sdk.Context) { // add accounts and set total supply totalSupplyAmt := initAmt.MulRaw(int64(len(valAddresses))) totalSupply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, totalSupplyAmt)) - suite.app.BankKeeper.SetSupply(ctx, banktypes.NewSupply(totalSupply)) + suite.NoError(suite.app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, totalSupply)) for _, addr := range valAddresses { - err := suite.app.BankKeeper.AddCoins(ctx, sdk.AccAddress(addr), initCoins) - suite.NoError(err) + suite.NoError(suite.app.BankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, (sdk.AccAddress)(addr), initCoins)) } } diff --git a/x/feegrant/ante/fee_test.go b/x/feegrant/ante/fee_test.go index fe7bc4208a98..1a924db6a387 100644 --- a/x/feegrant/ante/fee_test.go +++ b/x/feegrant/ante/fee_test.go @@ -56,7 +56,7 @@ func (suite *AnteTestSuite) SetupTest(isCheckTx bool) { } func (suite *AnteTestSuite) TestDeductFeesNoDelegation() { - suite.SetupTest(true) + suite.SetupTest(false) // setup app, ctx := suite.app, suite.ctx @@ -77,17 +77,15 @@ func (suite *AnteTestSuite) TestDeductFeesNoDelegation() { priv5, _, addr5 := testdata.KeyTestPubAddr() // Set addr1 with insufficient funds - acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) - app.AccountKeeper.SetAccount(ctx, acc1) - app.BankKeeper.SetBalances(ctx, addr1, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(10))}) + err := simapp.FundAccount(suite.app, suite.ctx, addr1, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(10))}) + suite.Require().NoError(err) // Set addr2 with more funds - acc2 := app.AccountKeeper.NewAccountWithAddress(ctx, addr2) - app.AccountKeeper.SetAccount(ctx, acc2) - app.BankKeeper.SetBalances(ctx, addr2, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(99999))}) + err = simapp.FundAccount(suite.app, suite.ctx, addr2, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(99999))}) + suite.Require().NoError(err) // grant fee allowance from `addr2` to `addr3` (plenty to pay) - err := app.FeeGrantKeeper.GrantFeeAllowance(ctx, addr2, addr3, &types.BasicFeeAllowance{ + err = app.FeeGrantKeeper.GrantFeeAllowance(ctx, addr2, addr3, &types.BasicFeeAllowance{ SpendLimit: sdk.NewCoins(sdk.NewInt64Coin("atom", 500)), }) suite.Require().NoError(err) diff --git a/x/feegrant/simulation/operations_test.go b/x/feegrant/simulation/operations_test.go index 7c2593a5302a..85db81f2ce82 100644 --- a/x/feegrant/simulation/operations_test.go +++ b/x/feegrant/simulation/operations_test.go @@ -37,19 +37,15 @@ func (suite *SimTestSuite) SetupTest() { } func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { - app, ctx := suite.app, suite.ctx accounts := simtypes.RandomAccounts(r, n) - require := suite.Require() initAmt := sdk.TokensFromConsensusPower(200) initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) // add coins to the accounts for _, account := range accounts { - acc := app.AccountKeeper.NewAccountWithAddress(ctx, account.Address) - app.AccountKeeper.SetAccount(ctx, acc) - err := app.BankKeeper.SetBalances(ctx, account.Address, initCoins) - require.NoError(err) + err := simapp.FundAccount(suite.app, suite.ctx, account.Address, initCoins) + suite.Require().NoError(err) } return accounts diff --git a/x/genutil/gentx_test.go b/x/genutil/gentx_test.go index b4b843bc986e..79c5bad39c78 100644 --- a/x/genutil/gentx_test.go +++ b/x/genutil/gentx_test.go @@ -64,9 +64,7 @@ func (suite *GenTxTestSuite) setAccountBalance(addr sdk.AccAddress, amount int64 acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) - err := suite.app.BankKeeper.SetBalances( - suite.ctx, addr, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 25)}, - ) + err := simapp.FundAccount(suite.app, suite.ctx, addr, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 25)}) suite.Require().NoError(err) bankGenesisState := suite.app.BankKeeper.ExportGenesis(suite.ctx) diff --git a/x/gov/genesis.go b/x/gov/genesis.go index 553edbaa0f77..62a194d9c0a9 100644 --- a/x/gov/genesis.go +++ b/x/gov/genesis.go @@ -41,14 +41,16 @@ func InitGenesis(ctx sdk.Context, ak types.AccountKeeper, bk types.BankKeeper, k k.SetProposal(ctx, proposal) } - // add coins if not provided on genesis - if bk.GetAllBalances(ctx, moduleAcc.GetAddress()).IsZero() { - if err := bk.SetBalances(ctx, moduleAcc.GetAddress(), totalDeposits); err != nil { - panic(err) - } - + // if account has zero balance it probably means it's not set, so we set it + balance := bk.GetAllBalances(ctx, moduleAcc.GetAddress()) + if balance.IsZero() { ak.SetModuleAccount(ctx, moduleAcc) } + + // check if total deposits equals balance, if it doesn't panic because there were export/import errors + if !balance.IsEqual(totalDeposits) { + panic(fmt.Sprintf("expected module account was %s but we got %s", balance.String(), totalDeposits.String())) + } } // ExportGenesis - output genesis parameters diff --git a/x/gov/genesis_test.go b/x/gov/genesis_test.go index 2fb3aea9467b..f504ef5a1f45 100644 --- a/x/gov/genesis_test.go +++ b/x/gov/genesis_test.go @@ -11,6 +11,7 @@ import ( dbm "github.com/tendermint/tm-db" "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -111,6 +112,27 @@ func TestImportExportQueues(t *testing.T) { require.True(t, proposal2.Status == types.StatusRejected) } +func TestImportExportQueues_ErrorUnconsistentState(t *testing.T) { + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, tmproto.Header{}) + require.Panics(t, func() { + gov.InitGenesis(ctx, app.AccountKeeper, app.BankKeeper, app.GovKeeper, &types.GenesisState{ + Deposits: types.Deposits{ + { + 1234, + "me", + sdk.Coins{ + { + "stake", + sdk.NewInt(1234), + }, + }, + }, + }, + }) + }) +} + func TestEqualProposals(t *testing.T) { app := simapp.Setup(false) ctx := app.BaseApp.NewContext(false, tmproto.Header{}) diff --git a/x/gov/simulation/operations_test.go b/x/gov/simulation/operations_test.go index 8d1076fffd6d..2d3bbe22fcd7 100644 --- a/x/gov/simulation/operations_test.go +++ b/x/gov/simulation/operations_test.go @@ -271,8 +271,7 @@ func getTestingAccounts(t *testing.T, r *rand.Rand, app *simapp.SimApp, ctx sdk. for _, account := range accounts { acc := app.AccountKeeper.NewAccountWithAddress(ctx, account.Address) app.AccountKeeper.SetAccount(ctx, acc) - err := app.BankKeeper.SetBalances(ctx, account.Address, initCoins) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, account.Address, initCoins)) } return accounts diff --git a/x/gov/types/expected_keepers.go b/x/gov/types/expected_keepers.go index f862a9bce563..1ad39abca0ec 100644 --- a/x/gov/types/expected_keepers.go +++ b/x/gov/types/expected_keepers.go @@ -41,7 +41,6 @@ type AccountKeeper interface { type BankKeeper interface { GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin - SetBalances(ctx sdk.Context, addr sdk.AccAddress, balances sdk.Coins) error LockedCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins diff --git a/x/ibc/applications/transfer/keeper/mbt_relay_test.go b/x/ibc/applications/transfer/keeper/mbt_relay_test.go index defcbbbc8db6..cd64fbabc252 100644 --- a/x/ibc/applications/transfer/keeper/mbt_relay_test.go +++ b/x/ibc/applications/transfer/keeper/mbt_relay_test.go @@ -262,22 +262,6 @@ func BankOfChain(chain *ibctesting.TestChain) Bank { return bank } -// Set balances of the chain bank for balances present in the bank -func (suite *KeeperTestSuite) SetChainBankBalances(chain *ibctesting.TestChain, bank *Bank) error { - for coin, amount := range bank.balances { - address, err := sdk.AccAddressFromBech32(coin.Address) - if err != nil { - return err - } - trace := types.ParseDenomTrace(coin.Denom) - err = chain.App.BankKeeper.SetBalance(chain.GetContext(), address, sdk.NewCoin(trace.IBCDenom(), amount)) - if err != nil { - return err - } - } - return nil -} - // Check that the state of the bank is the bankBefore + expectedBankChange func (suite *KeeperTestSuite) CheckBankBalances(chain *ibctesting.TestChain, bankBefore *Bank, expectedBankChange *Bank) error { bankAfter := BankOfChain(chain) diff --git a/x/ibc/applications/transfer/keeper/relay_test.go b/x/ibc/applications/transfer/keeper/relay_test.go index 9f303175175f..89058ac2952a 100644 --- a/x/ibc/applications/transfer/keeper/relay_test.go +++ b/x/ibc/applications/transfer/keeper/relay_test.go @@ -3,6 +3,8 @@ package keeper_test import ( "fmt" + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" @@ -257,8 +259,7 @@ func (suite *KeeperTestSuite) TestOnAcknowledgementPacket() { trace = types.ParseDenomTrace(sdk.DefaultBondDenom) coin := sdk.NewCoin(sdk.DefaultBondDenom, amount) - err := suite.chainA.App.BankKeeper.AddCoins(suite.chainA.GetContext(), escrow, sdk.NewCoins(coin)) - suite.Require().NoError(err) + suite.Require().NoError(simapp.FundAccount(suite.chainA.App, suite.chainA.GetContext(), escrow, sdk.NewCoins(coin))) }, false, true}, {"unsuccessful refund from source", failedAck, func() { @@ -270,8 +271,7 @@ func (suite *KeeperTestSuite) TestOnAcknowledgementPacket() { trace = types.ParseDenomTrace(types.GetPrefixedDenom(channelA.PortID, channelA.ID, sdk.DefaultBondDenom)) coin := sdk.NewCoin(trace.IBCDenom(), amount) - err := suite.chainA.App.BankKeeper.AddCoins(suite.chainA.GetContext(), escrow, sdk.NewCoins(coin)) - suite.Require().NoError(err) + suite.Require().NoError(simapp.FundAccount(suite.chainA.App, suite.chainA.GetContext(), escrow, sdk.NewCoins(coin))) }, false, true}, } @@ -332,8 +332,7 @@ func (suite *KeeperTestSuite) TestOnTimeoutPacket() { trace = types.ParseDenomTrace(sdk.DefaultBondDenom) coin := sdk.NewCoin(trace.IBCDenom(), amount) - err := suite.chainA.App.BankKeeper.AddCoins(suite.chainA.GetContext(), escrow, sdk.NewCoins(coin)) - suite.Require().NoError(err) + suite.Require().NoError(simapp.FundAccount(suite.chainA.App, suite.chainA.GetContext(), escrow, sdk.NewCoins(coin))) }, true}, {"successful timeout from external chain", func() { @@ -341,8 +340,7 @@ func (suite *KeeperTestSuite) TestOnTimeoutPacket() { trace = types.ParseDenomTrace(types.GetPrefixedDenom(channelA.PortID, channelA.ID, sdk.DefaultBondDenom)) coin := sdk.NewCoin(trace.IBCDenom(), amount) - err := suite.chainA.App.BankKeeper.AddCoins(suite.chainA.GetContext(), escrow, sdk.NewCoins(coin)) - suite.Require().NoError(err) + suite.Require().NoError(simapp.FundAccount(suite.chainA.App, suite.chainA.GetContext(), escrow, sdk.NewCoins(coin))) }, true}, {"no balance for coin denom", func() { diff --git a/x/slashing/simulation/operations_test.go b/x/slashing/simulation/operations_test.go index 15764c631ebf..a224d460a310 100644 --- a/x/slashing/simulation/operations_test.go +++ b/x/slashing/simulation/operations_test.go @@ -123,8 +123,7 @@ func getTestingAccounts(t *testing.T, r *rand.Rand, app *simapp.SimApp, ctx sdk. for _, account := range accounts { acc := app.AccountKeeper.NewAccountWithAddress(ctx, account.Address) app.AccountKeeper.SetAccount(ctx, acc) - err := app.BankKeeper.SetBalances(ctx, account.Address, initCoins) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, account.Address, initCoins)) } return accounts diff --git a/x/slashing/types/expected_keepers.go b/x/slashing/types/expected_keepers.go index 538a030baac0..9710ad1786e7 100644 --- a/x/slashing/types/expected_keepers.go +++ b/x/slashing/types/expected_keepers.go @@ -19,7 +19,6 @@ type AccountKeeper interface { type BankKeeper interface { GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin - SetBalances(ctx sdk.Context, addr sdk.AccAddress, balances sdk.Coins) error LockedCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins } diff --git a/x/staking/genesis.go b/x/staking/genesis.go index 02f6bc317473..96c7be8e44dc 100644 --- a/x/staking/genesis.go +++ b/x/staking/genesis.go @@ -105,30 +105,28 @@ func InitGenesis( if bondedPool == nil { panic(fmt.Sprintf("%s module account has not been set", types.BondedPoolName)) } - // TODO remove with genesis 2-phases refactor https://github.com/cosmos/cosmos-sdk/issues/2862 - // add coins if not provided on genesis - if bankKeeper.GetAllBalances(ctx, bondedPool.GetAddress()).IsZero() { - if err := bankKeeper.SetBalances(ctx, bondedPool.GetAddress(), bondedCoins); err != nil { - panic(err) - } - + bondedBalance := bankKeeper.GetAllBalances(ctx, bondedPool.GetAddress()) + if bondedBalance.IsZero() { accountKeeper.SetModuleAccount(ctx, bondedPool) } - + // if balance is different from bonded coins panic because genesis is most likely malformed + if !bondedBalance.IsEqual(bondedCoins) { + panic(fmt.Sprintf("bonded pool balance is different from bonded coins: %s <-> %s", bondedBalance, bondedCoins)) + } notBondedPool := keeper.GetNotBondedPool(ctx) if notBondedPool == nil { panic(fmt.Sprintf("%s module account has not been set", types.NotBondedPoolName)) } - if bankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()).IsZero() { - if err := bankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), notBondedCoins); err != nil { - panic(err) - } - + notBondedBalance := bankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()) + if notBondedBalance.IsZero() { accountKeeper.SetModuleAccount(ctx, notBondedPool) } - + // if balance is different from non bonded coins panic because genesis is most likely malformed + if !notBondedBalance.IsEqual(notBondedCoins) { + panic(fmt.Sprintf("not bonded pool balance is different from not bonded coins: %s <-> %s", notBondedBalance, notBondedCoins)) + } // don't need to run Tendermint updates if we exported if data.Exported { for _, lv := range data.LastValidatorPowers { diff --git a/x/staking/genesis_test.go b/x/staking/genesis_test.go index 28e3dec8a0fd..67f6c7a872ae 100644 --- a/x/staking/genesis_test.go +++ b/x/staking/genesis_test.go @@ -2,47 +2,39 @@ package staking_test import ( "fmt" + "log" "testing" + auth "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/staking" "github.com/cosmos/cosmos-sdk/x/staking/teststaking" "github.com/cosmos/cosmos-sdk/x/staking/types" ) -func bootstrapGenesisTest(t *testing.T, power int64, numAddrs int) (*simapp.SimApp, sdk.Context, []sdk.AccAddress) { +func bootstrapGenesisTest(numAddrs int) (*simapp.SimApp, sdk.Context, []sdk.AccAddress) { _, app, ctx := getBaseSimappWithCustomKeeper() addrDels, _ := generateAddresses(app, ctx, numAddrs, sdk.NewInt(10000)) - - amt := sdk.TokensFromConsensusPower(power) - totalSupply := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), amt.MulRaw(int64(len(addrDels))))) - - notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - err := app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), totalSupply) - require.NoError(t, err) - - app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) - app.BankKeeper.SetSupply(ctx, banktypes.NewSupply(totalSupply)) - return app, ctx, addrDels } func TestInitGenesis(t *testing.T) { - app, ctx, addrs := bootstrapGenesisTest(t, 1000, 10) + app, ctx, addrs := bootstrapGenesisTest(10) valTokens := sdk.TokensFromConsensusPower(1) params := app.StakingKeeper.GetParams(ctx) - validators := make([]types.Validator, 2) + validators := app.StakingKeeper.GetAllValidators(ctx) var delegations []types.Delegation pk0, err := codectypes.NewAnyWithValue(PKs[0]) @@ -52,19 +44,40 @@ func TestInitGenesis(t *testing.T) { require.NoError(t, err) // initialize the validators - validators[0].OperatorAddress = sdk.ValAddress(addrs[0]).String() - validators[0].ConsensusPubkey = pk0 - validators[0].Description = types.NewDescription("hoop", "", "", "", "") - validators[0].Status = types.Bonded - validators[0].Tokens = valTokens - validators[0].DelegatorShares = valTokens.ToDec() - validators[1].OperatorAddress = sdk.ValAddress(addrs[1]).String() - validators[1].ConsensusPubkey = pk1 - validators[1].Description = types.NewDescription("bloop", "", "", "", "") - validators[1].Status = types.Bonded - validators[1].Tokens = valTokens - validators[1].DelegatorShares = valTokens.ToDec() + bondedVal1 := types.Validator{ + OperatorAddress: sdk.ValAddress(addrs[0]).String(), + ConsensusPubkey: pk0, + Status: types.Bonded, + Tokens: valTokens, + DelegatorShares: valTokens.ToDec(), + Description: types.NewDescription("hoop", "", "", "", ""), + } + bondedVal2 := types.Validator{ + OperatorAddress: sdk.ValAddress(addrs[1]).String(), + ConsensusPubkey: pk1, + Status: types.Bonded, + Tokens: valTokens, + DelegatorShares: valTokens.ToDec(), + Description: types.NewDescription("bloop", "", "", "", ""), + } + // append new bonded validators to the list + validators = append(validators, bondedVal1, bondedVal2) + log.Printf("%#v", len(validators)) + // mint coins in the bonded pool representing the validators coins + require.NoError(t, + simapp.FundAccount( + app, + ctx, + auth.NewModuleAddress(types.BondedPoolName), + sdk.NewCoins( + sdk.NewCoin( + params.BondDenom, + valTokens.MulRaw((int64)(len(validators))), + ), + ), + ), + ) genesisState := types.NewGenesisState(params, validators, delegations) vals := staking.InitGenesis(ctx, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, genesisState) @@ -97,16 +110,63 @@ func TestInitGenesis(t *testing.T) { require.Equal(t, abcivals, vals) } +func TestInitGenesis_PoolsBalanceMismatch(t *testing.T) { + app := simapp.Setup(false) + ctx := app.NewContext(false, tmproto.Header{}) + + consPub, err := codectypes.NewAnyWithValue(PKs[0]) + require.NoError(t, err) + + // create mock validator + validator := types.Validator{ + OperatorAddress: sdk.ValAddress("12345678901234567890").String(), + ConsensusPubkey: consPub, + Jailed: false, + Tokens: sdk.NewInt(10), + DelegatorShares: sdk.NewInt(10).ToDec(), + Description: types.NewDescription("bloop", "", "", "", ""), + } + // valid params + params := types.Params{ + UnbondingTime: 10000, + MaxValidators: 1, + MaxEntries: 10, + BondDenom: "stake", + } + + // test + + require.Panics(t, func() { + // setting validator status to bonded so the balance counts towards bonded pool + validator.Status = types.Bonded + staking.InitGenesis(ctx, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, &types.GenesisState{ + Params: params, + Validators: []types.Validator{validator}, + }) + }, "should panic because bonded pool balance is different from bonded pool coins") + + require.Panics(t, func() { + // setting validator status to unbonded so the balance counts towards not bonded pool + validator.Status = types.Unbonded + staking.InitGenesis(ctx, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, &types.GenesisState{ + Params: params, + Validators: []types.Validator{validator}, + }) + }, "should panic because not bonded pool balance is different from not bonded pool coins") +} + func TestInitGenesisLargeValidatorSet(t *testing.T) { size := 200 require.True(t, size > 100) - app, ctx, addrs := bootstrapGenesisTest(t, 1000, 200) + app, ctx, addrs := bootstrapGenesisTest(200) params := app.StakingKeeper.GetParams(ctx) delegations := []types.Delegation{} validators := make([]types.Validator, size) var err error + + bondedPoolAmt := sdk.ZeroInt() for i := range validators { validators[i], err = types.NewValidator(sdk.ValAddress(addrs[i]), PKs[i], types.NewDescription(fmt.Sprintf("#%d", i), "", "", "", "")) @@ -119,9 +179,22 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) { } validators[i].Tokens = tokens validators[i].DelegatorShares = tokens.ToDec() + // add bonded coins + bondedPoolAmt = bondedPoolAmt.Add(tokens) } - genesisState := types.NewGenesisState(params, validators, delegations) + // mint coins in the bonded pool representing the validators coins + require.NoError(t, + simapp.FundAccount( + app, + ctx, + auth.NewModuleAddress(types.BondedPoolName), + sdk.NewCoins( + sdk.NewCoin(params.BondDenom, bondedPoolAmt), + ), + ), + ) + vals := staking.InitGenesis(ctx, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, genesisState) abcivals := make([]abci.ValidatorUpdate, 100) diff --git a/x/staking/handler_test.go b/x/staking/handler_test.go index 4b48f09427c9..bceef6b3f4e7 100644 --- a/x/staking/handler_test.go +++ b/x/staking/handler_test.go @@ -20,7 +20,6 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/staking" "github.com/cosmos/cosmos-sdk/x/staking/keeper" "github.com/cosmos/cosmos-sdk/x/staking/teststaking" @@ -36,12 +35,10 @@ func bootstrapHandlerGenesisTest(t *testing.T, power int64, numAddrs int, accAmo totalSupply := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), amt.MulRaw(int64(len(addrDels))))) notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - err := app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), totalSupply) - require.NoError(t, err) + // set non bonded pool balance app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) - app.BankKeeper.SetSupply(ctx, banktypes.NewSupply(totalSupply)) - + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), totalSupply)) return app, ctx, addrDels, addrVals } diff --git a/x/staking/keeper/delegation_test.go b/x/staking/keeper/delegation_test.go index 77f4cb8e2c81..6458c35d3624 100644 --- a/x/staking/keeper/delegation_test.go +++ b/x/staking/keeper/delegation_test.go @@ -186,13 +186,7 @@ func TestUnbondDelegation(t *testing.T) { startTokens := sdk.TokensFromConsensusPower(10) notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, - app.BankKeeper.SetBalances( - ctx, - notBondedPool.GetAddress(), - sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), startTokens)), - ), - ) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), startTokens)))) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) // create a validator and a delegator to that validator @@ -233,8 +227,7 @@ func TestUnbondingDelegationsMaxEntries(t *testing.T) { bondDenom := app.StakingKeeper.BondDenom(ctx) notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - err := app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens))) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) // create a validator and a delegator to that validator @@ -272,7 +265,7 @@ func TestUnbondingDelegationsMaxEntries(t *testing.T) { oldNotBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount // an additional unbond should fail due to max entries - _, err = app.StakingKeeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(1)) + _, err := app.StakingKeeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(1)) require.Error(t, err) newBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount @@ -322,9 +315,7 @@ func TestUndelegateSelfDelegationBelowMinSelfDelegation(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - oldNotBonded := app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(delCoins...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true) @@ -336,9 +327,7 @@ func TestUndelegateSelfDelegationBelowMinSelfDelegation(t *testing.T) { // add bonded tokens to pool for delegations bondedPool := app.StakingKeeper.GetBondedPool(ctx) - oldBonded := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress()) - err = app.BankKeeper.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, bondedPool.GetAddress(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) // create a second delegation to this validator @@ -348,9 +337,7 @@ func TestUndelegateSelfDelegationBelowMinSelfDelegation(t *testing.T) { require.Equal(t, delTokens, issuedShares.RoundInt()) // add bonded tokens to pool for delegations - oldBonded = app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress()) - err = app.BankKeeper.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, bondedPool.GetAddress(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true) @@ -358,7 +345,7 @@ func TestUndelegateSelfDelegationBelowMinSelfDelegation(t *testing.T) { app.StakingKeeper.SetDelegation(ctx, delegation) val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) - _, err = app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], sdk.TokensFromConsensusPower(6).ToDec()) + _, err := app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], sdk.TokensFromConsensusPower(6).ToDec()) require.NoError(t, err) // end block @@ -388,9 +375,7 @@ func TestUndelegateFromUnbondingValidator(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - oldNotBonded := app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(delCoins...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true) @@ -400,9 +385,7 @@ func TestUndelegateFromUnbondingValidator(t *testing.T) { app.StakingKeeper.SetDelegation(ctx, selfDelegation) bondedPool := app.StakingKeeper.GetBondedPool(ctx) - oldBonded := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress()) - err = app.BankKeeper.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, bondedPool.GetAddress(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) // create a second delegation to this validator @@ -411,18 +394,14 @@ func TestUndelegateFromUnbondingValidator(t *testing.T) { validator, issuedShares = validator.AddTokensFromDel(delTokens) require.Equal(t, delTokens, issuedShares.RoundInt()) - oldBonded = app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress()) - err = app.BankKeeper.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, bondedPool.GetAddress(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true) delegation := types.NewDelegation(addrDels[1], addrVals[0], issuedShares) app.StakingKeeper.SetDelegation(ctx, delegation) - oldBonded = app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress()) - err = app.BankKeeper.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, bondedPool.GetAddress(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) header := ctx.BlockHeader() @@ -434,7 +413,7 @@ func TestUndelegateFromUnbondingValidator(t *testing.T) { // unbond the all self-delegation to put validator in unbonding state val0AccAddr := sdk.AccAddress(addrVals[0]) - _, err = app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec()) + _, err := app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec()) require.NoError(t, err) // end block @@ -474,9 +453,7 @@ func TestUndelegateFromUnbondedValidator(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - oldNotBonded := app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(delCoins...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) // create a validator with a self-delegation @@ -494,9 +471,7 @@ func TestUndelegateFromUnbondedValidator(t *testing.T) { app.StakingKeeper.SetDelegation(ctx, selfDelegation) bondedPool := app.StakingKeeper.GetBondedPool(ctx) - oldBonded := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress()) - err = app.BankKeeper.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, bondedPool.GetAddress(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) // create a second delegation to this validator @@ -512,7 +487,7 @@ func TestUndelegateFromUnbondedValidator(t *testing.T) { ctx = ctx.WithBlockTime(time.Unix(333, 0)) // unbond the all self-delegation to put validator in unbonding state - _, err = app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], valTokens.ToDec()) + _, err := app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], valTokens.ToDec()) require.NoError(t, err) // end block @@ -558,9 +533,7 @@ func TestUnbondingAllDelegationFromValidator(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - oldNotBonded := app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(delCoins...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) //create a validator with a self-delegation @@ -584,9 +557,7 @@ func TestUnbondingAllDelegationFromValidator(t *testing.T) { require.Equal(t, delTokens, issuedShares.RoundInt()) bondedPool := app.StakingKeeper.GetBondedPool(ctx) - oldBonded := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress()) - err = app.BankKeeper.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, bondedPool.GetAddress(), delCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true) @@ -599,7 +570,7 @@ func TestUnbondingAllDelegationFromValidator(t *testing.T) { ctx = ctx.WithBlockTime(time.Unix(333, 0)) // unbond the all self-delegation to put validator in unbonding state - _, err = app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], valTokens.ToDec()) + _, err := app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], valTokens.ToDec()) require.NoError(t, err) // end block @@ -725,9 +696,7 @@ func TestRedelegateToSameValidator(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - oldNotBonded := app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), startCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) // create a validator with a self-delegation @@ -741,7 +710,7 @@ func TestRedelegateToSameValidator(t *testing.T) { selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) app.StakingKeeper.SetDelegation(ctx, selfDelegation) - _, err = app.StakingKeeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[0], sdk.NewDec(5)) + _, err := app.StakingKeeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[0], sdk.NewDec(5)) require.Error(t, err) } @@ -756,9 +725,7 @@ func TestRedelegationMaxEntries(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - oldNotBonded := app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), startCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) // create a validator with a self-delegation @@ -790,7 +757,7 @@ func TestRedelegationMaxEntries(t *testing.T) { } // an additional redelegation should fail due to max entries - _, err = app.StakingKeeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], sdk.NewDec(1)) + _, err := app.StakingKeeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], sdk.NewDec(1)) require.Error(t, err) // mature redelegations @@ -814,9 +781,7 @@ func TestRedelegateSelfDelegation(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - oldNotBonded := app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), startCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) //create a validator with a self-delegation @@ -849,7 +814,7 @@ func TestRedelegateSelfDelegation(t *testing.T) { delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) app.StakingKeeper.SetDelegation(ctx, delegation) - _, err = app.StakingKeeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], delTokens.ToDec()) + _, err := app.StakingKeeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], delTokens.ToDec()) require.NoError(t, err) // end block @@ -872,9 +837,7 @@ func TestRedelegateFromUnbondingValidator(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - oldNotBonded := app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), startCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) //create a validator with a self-delegation @@ -912,7 +875,7 @@ func TestRedelegateFromUnbondingValidator(t *testing.T) { ctx = ctx.WithBlockHeader(header) // unbond the all self-delegation to put validator in unbonding state - _, err = app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec()) + _, err := app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec()) require.NoError(t, err) // end block @@ -956,9 +919,7 @@ func TestRedelegateFromUnbondedValidator(t *testing.T) { // add bonded tokens to pool for delegations notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - oldNotBonded := app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), startCoins)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) //create a validator with a self-delegation @@ -993,7 +954,7 @@ func TestRedelegateFromUnbondedValidator(t *testing.T) { ctx = ctx.WithBlockTime(time.Unix(333, 0)) // unbond the all self-delegation to put validator in unbonding state - _, err = app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec()) + _, err := app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec()) require.NoError(t, err) // end block diff --git a/x/staking/keeper/slash_test.go b/x/staking/keeper/slash_test.go index 356c022e4e26..146ed5868732 100644 --- a/x/staking/keeper/slash_test.go +++ b/x/staking/keeper/slash_test.go @@ -10,7 +10,6 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/staking/keeper" "github.com/cosmos/cosmos-sdk/x/staking/teststaking" "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -26,8 +25,7 @@ func bootstrapSlashTest(t *testing.T, power int64) (*simapp.SimApp, sdk.Context, totalSupply := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), amt.MulRaw(int64(len(addrDels))))) notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - err := app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), totalSupply) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), totalSupply)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) @@ -35,11 +33,9 @@ func bootstrapSlashTest(t *testing.T, power int64) (*simapp.SimApp, sdk.Context, bondedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), amt.MulRaw(numVals))) bondedPool := app.StakingKeeper.GetBondedPool(ctx) - err = app.BankKeeper.SetBalances(ctx, bondedPool.GetAddress(), bondedCoins) - require.NoError(t, err) - + // set bonded pool balance app.AccountKeeper.SetModuleAccount(ctx, bondedPool) - app.BankKeeper.SetSupply(ctx, banktypes.NewSupply(totalSupply)) + require.NoError(t, simapp.FundAccount(app, ctx, bondedPool.GetAddress(), bondedCoins)) for i := int64(0); i < numVals; i++ { validator := teststaking.NewValidator(t, addrVals[i], PKs[i]) @@ -129,7 +125,7 @@ func TestSlashRedelegation(t *testing.T) { bondedPool := app.StakingKeeper.GetBondedPool(ctx) balances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress()) - require.NoError(t, app.BankKeeper.SetBalances(ctx, bondedPool.GetAddress(), balances.Add(startCoins...))) + require.NoError(t, simapp.FundAccount(app, ctx, bondedPool.GetAddress(), startCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) // set a redelegation with an expiration timestamp beyond which the @@ -408,10 +404,7 @@ func TestSlashWithRedelegation(t *testing.T) { notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) rdCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, rdTokens.MulRaw(2))) - balances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress()) - - err := app.BankKeeper.SetBalances(ctx, bondedPool.GetAddress(), balances.Add(rdCoins...)) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, bondedPool.GetAddress(), rdCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) @@ -574,11 +567,9 @@ func TestSlashBoth(t *testing.T) { bondedPool := app.StakingKeeper.GetBondedPool(ctx) notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - bondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress()) - require.NoError(t, app.BankKeeper.SetBalances(ctx, bondedPool.GetAddress(), bondedPoolBalances.Add(bondedCoins...))) + require.NoError(t, simapp.FundAccount(app, ctx, bondedPool.GetAddress(), bondedCoins)) - notBondedPoolBalances := app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()) - require.NoError(t, app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), notBondedPoolBalances.Add(notBondedCoins...))) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), notBondedCoins)) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) diff --git a/x/staking/keeper/validator_test.go b/x/staking/keeper/validator_test.go index 869644070507..3a1842397c59 100644 --- a/x/staking/keeper/validator_test.go +++ b/x/staking/keeper/validator_test.go @@ -13,7 +13,6 @@ import ( cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/staking/keeper" "github.com/cosmos/cosmos-sdk/x/staking/teststaking" "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -34,11 +33,10 @@ func bootstrapValidatorTest(t testing.TB, power int64, numAddrs int) (*simapp.Si totalSupply := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), amt.MulRaw(int64(len(addrDels))))) notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - err := app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), totalSupply) - require.NoError(t, err) - + // set bonded pool supply app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) - app.BankKeeper.SetSupply(ctx, banktypes.NewSupply(totalSupply)) + + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), totalSupply)) return app, ctx, addrDels, addrVals } @@ -115,11 +113,9 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) { bondedPool := app.StakingKeeper.GetBondedPool(ctx) notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - err := app.BankKeeper.SetBalances(ctx, bondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.TokensFromConsensusPower(1234)))) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, bondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.TokensFromConsensusPower(1234))))) - err = app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.TokensFromConsensusPower(10000)))) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.TokensFromConsensusPower(10000))))) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) @@ -167,11 +163,9 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { app.StakingKeeper.SetParams(ctx, params) // create a random pool - err := app.BankKeeper.SetBalances(ctx, bondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.TokensFromConsensusPower(1234)))) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, bondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.TokensFromConsensusPower(1234))))) - err = app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.TokensFromConsensusPower(10000)))) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.TokensFromConsensusPower(10000))))) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) @@ -225,8 +219,7 @@ func TestSlashToZeroPowerRemoved(t *testing.T) { bondedPool := app.StakingKeeper.GetBondedPool(ctx) - err := app.BankKeeper.SetBalances(ctx, bondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), valTokens))) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, bondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), valTokens)))) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) @@ -431,11 +424,9 @@ func TestGetValidatorSortingMixed(t *testing.T) { bondedPool := app.StakingKeeper.GetBondedPool(ctx) notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - err := app.BankKeeper.SetBalances(ctx, bondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.TokensFromConsensusPower(501)))) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, bondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.TokensFromConsensusPower(501))))) - err = app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.TokensFromConsensusPower(0)))) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.TokensFromConsensusPower(0))))) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) @@ -509,9 +500,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { validators[i], _ = validators[i].AddTokensFromDel(tokens) notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - balances := app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()) - require.NoError(t, app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), balances.Add(sdk.NewCoin(params.BondDenom, tokens)))) - + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, tokens)))) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) validators[i] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[i], true) } @@ -529,9 +518,8 @@ func TestGetValidatorsEdgeCases(t *testing.T) { notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) newTokens := sdk.NewCoins() - balances := app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()) - require.NoError(t, app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), balances.Add(newTokens...))) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), newTokens)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) // test that the two largest validators are @@ -563,8 +551,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx) newTokens = sdk.NewCoins(sdk.NewCoin(params.BondDenom, sdk.TokensFromConsensusPower(1))) - balances = app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()) - require.NoError(t, app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), balances.Add(newTokens...))) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), newTokens)) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) validators[3] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true) @@ -579,8 +566,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { validators[3], _ = validators[3].RemoveDelShares(sdk.NewDec(201)) bondedPool := app.StakingKeeper.GetBondedPool(ctx) - balances = app.BankKeeper.GetAllBalances(ctx, bondedPool.GetAddress()) - require.NoError(t, app.BankKeeper.SetBalances(ctx, bondedPool.GetAddress(), balances.Add(sdk.NewCoin(params.BondDenom, rmTokens)))) + require.NoError(t, simapp.FundAccount(app, ctx, bondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, rmTokens)))) app.AccountKeeper.SetModuleAccount(ctx, bondedPool) validators[3] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true) @@ -594,8 +580,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { validators[3], _ = validators[3].AddTokensFromDel(sdk.NewInt(200)) notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx) - balances = app.BankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()) - require.NoError(t, app.BankKeeper.SetBalances(ctx, notBondedPool.GetAddress(), balances.Add(sdk.NewCoin(params.BondDenom, sdk.NewInt(200))))) + require.NoError(t, simapp.FundAccount(app, ctx, notBondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, sdk.NewInt(200))))) app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) validators[3] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true) diff --git a/x/staking/simulation/operations_test.go b/x/staking/simulation/operations_test.go index fca3b78125a9..8930e2921ee4 100644 --- a/x/staking/simulation/operations_test.go +++ b/x/staking/simulation/operations_test.go @@ -283,8 +283,7 @@ func getTestingAccounts(t *testing.T, r *rand.Rand, app *simapp.SimApp, ctx sdk. for _, account := range accounts { acc := app.AccountKeeper.NewAccountWithAddress(ctx, account.Address) app.AccountKeeper.SetAccount(ctx, acc) - err := app.BankKeeper.SetBalances(ctx, account.Address, initCoins) - require.NoError(t, err) + require.NoError(t, simapp.FundAccount(app, ctx, account.Address, initCoins)) } return accounts diff --git a/x/staking/types/expected_keepers.go b/x/staking/types/expected_keepers.go index 1c1d7f7de96b..07ceb7af1787 100644 --- a/x/staking/types/expected_keepers.go +++ b/x/staking/types/expected_keepers.go @@ -28,7 +28,6 @@ type AccountKeeper interface { type BankKeeper interface { GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin - SetBalances(ctx sdk.Context, addr sdk.AccAddress, balances sdk.Coins) error LockedCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins From 53637b607f38cb36be445f67803049ff11516ff8 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Wed, 17 Feb 2021 20:57:28 -0300 Subject: [PATCH 145/152] bank: additional denom metadata test case (#8612) --- x/bank/types/metadata_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/x/bank/types/metadata_test.go b/x/bank/types/metadata_test.go index 64241e6098e0..8ec2fe52ec02 100644 --- a/x/bank/types/metadata_test.go +++ b/x/bank/types/metadata_test.go @@ -29,6 +29,18 @@ func TestMetadataValidate(t *testing.T) { }, false, }, + { + "base coin is display coin", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"atom", uint32(0), []string{"ATOM"}}, + }, + Base: "atom", + Display: "atom", + }, + false, + }, {"empty metadata", types.Metadata{}, true}, { "invalid base denom", From b4820fe491e91cd95340f2f7b606adab454a7636 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 18 Feb 2021 08:33:56 +0000 Subject: [PATCH 146/152] Bump tendermint to v0.34.7 (#8616) Fix build failures. --- go.mod | 2 +- go.sum | 4 ++-- testutil/network/network.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 1258bf1bebdd..999997d9c68d 100644 --- a/go.mod +++ b/go.mod @@ -47,7 +47,7 @@ require ( github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2 github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 github.com/tendermint/go-amino v0.16.0 - github.com/tendermint/tendermint v0.34.4 + github.com/tendermint/tendermint v0.34.7 github.com/tendermint/tm-db v0.6.4 golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f diff --git a/go.sum b/go.sum index c6dd93072dbd..3e0e029f13fb 100644 --- a/go.sum +++ b/go.sum @@ -677,8 +677,8 @@ github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoM github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4= github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg= github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= -github.com/tendermint/tendermint v0.34.4 h1:E7qkvFGx27d8ugVLiAY2iWP6DL5cep3l/mpTaWKHyBA= -github.com/tendermint/tendermint v0.34.4/go.mod h1:JVuu3V1ZexOaZG8VJMRl8lnfrGw6hEB2TVnoUwKRbss= +github.com/tendermint/tendermint v0.34.7 h1:lvBJFNqpDuEzKfLZKtUXOL5dMOpqHonHlO6LCujyl6E= +github.com/tendermint/tendermint v0.34.7/go.mod h1:JVuu3V1ZexOaZG8VJMRl8lnfrGw6hEB2TVnoUwKRbss= github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI= github.com/tendermint/tm-db v0.6.3 h1:ZkhQcKnB8/2jr5EaZwGndN4owkPsGezW2fSisS9zGbg= github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8= diff --git a/testutil/network/network.go b/testutil/network/network.go index c73b69d18ab2..2475e36e0486 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -242,7 +242,7 @@ func New(t *testing.T, cfg Config) *Network { logger := log.NewNopLogger() if cfg.EnableLogging { logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) - logger, _ = tmflags.ParseLogLevel("info", logger, tmcfg.DefaultLogLevel()) + logger, _ = tmflags.ParseLogLevel("info", logger, tmcfg.DefaultLogLevel) } ctx.Logger = logger From 73e38e4009a57951b72e2998b4e3d5db2d499d04 Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Thu, 18 Feb 2021 19:00:19 +0100 Subject: [PATCH 147/152] Use service Msgs in CLI tx commands (#8512) * Use service Msgs in CLI tx commands * Update comment * Gracefully support amino signing * CLI to use svc msg * Fix lint * Use fq method name in events * Update tests * Fix quering events * Add docs * Fix test build * Fix events * Fix search for events * Handle old andd new event quering * Use merge events * Better encCfg * Add page in search * Fix tests * Update test and comments * Update x/auth/legacy/legacytx/stdsign.go Co-authored-by: atheeshp <59333759+atheeshp@users.noreply.github.com> * Fix conflict for weighted vote * Make CopyTx actually run * Fix CopyTx * Fix test * Add changelog entry * Remove useless code * Add msgs tests * Remove testing proto Msg via CLI * Fix lint * Fix test * Implement GetSignBytes on ServiceMsg * Fix %T Co-authored-by: atheeshp <59333759+atheeshp@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- CHANGELOG.md | 3 +- client/tx/legacy_test.go | 41 +++- docs/core/events.md | 2 +- server/grpc/server_test.go | 44 +--- types/service_msg.go | 16 +- x/auth/client/cli/cli_test.go | 19 +- x/auth/client/rest/rest_test.go | 4 +- x/auth/legacy/legacytx/stdsign.go | 3 + x/auth/tx/service_test.go | 14 +- x/auth/vesting/client/cli/tx.go | 8 +- x/authz/client/cli/cli_test.go | 2 +- x/authz/client/cli/tx.go | 12 +- x/bank/client/cli/cli_test.go | 60 +---- x/bank/client/cli/tx.go | 8 +- x/bank/client/testutil/cli_helpers.go | 95 ++++---- x/crisis/client/cli/tx.go | 8 +- x/distribution/client/cli/tx.go | 22 +- x/feegrant/client/cli/tx.go | 8 +- x/gov/client/cli/tx.go | 22 +- x/gov/client/utils/query.go | 221 ++++++++++++++----- x/gov/client/utils/query_test.go | 52 +++-- x/gov/types/msgs.go | 6 + x/ibc/applications/transfer/client/cli/tx.go | 8 +- x/ibc/core/02-client/client/cli/tx.go | 29 ++- x/ibc/core/03-connection/client/cli/tx.go | 29 ++- x/ibc/core/04-channel/client/cli/tx.go | 43 +++- x/params/client/cli/tx.go | 8 +- x/slashing/client/cli/tx.go | 8 +- x/staking/client/cli/tx.go | 42 +++- x/staking/client/rest/query.go | 22 +- x/staking/types/msg.go | 7 + x/upgrade/client/cli/tx.go | 15 +- 32 files changed, 544 insertions(+), 337 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d3afda47ee5..45c93da693c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,7 +38,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Client Breaking Changes -* [\#8363](https://github.com/cosmos/cosmos-sdk/issues/8363) Addresses no longer have a fixed 20-byte length. From the SDK modules' point of view, any 1-255 bytes-long byte array is a valid address. +* [\#8363](https://github.com/cosmos/cosmos-sdk/pull/8363) Addresses no longer have a fixed 20-byte length. From the SDK modules' point of view, any 1-255 bytes-long byte array is a valid address. +* [\#8346](https://github.com/cosmos/cosmos-sdk/pull/8346) All CLI `tx` commands generate ServiceMsgs by default. Graceful Amino support has been added to ServiceMsgs to support signing legacy Msgs. ### API Breaking Changes diff --git a/client/tx/legacy_test.go b/client/tx/legacy_test.go index b10c51e34402..5dcab771c495 100644 --- a/client/tx/legacy_test.go +++ b/client/tx/legacy_test.go @@ -13,6 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/simapp/params" "github.com/cosmos/cosmos-sdk/testutil/testdata" "github.com/cosmos/cosmos-sdk/types" + sdk "github.com/cosmos/cosmos-sdk/types" signing2 "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" "github.com/cosmos/cosmos-sdk/x/auth/signing" @@ -23,14 +24,13 @@ import ( const ( memo = "waboom" gas = uint64(10000) - timeoutHeight = 5 + timeoutHeight = uint64(5) ) var ( fee = types.NewCoins(types.NewInt64Coin("bam", 100)) _, pub1, addr1 = testdata.KeyTestPubAddr() _, _, addr2 = testdata.KeyTestPubAddr() - msg = banktypes.NewMsgSend(addr1, addr2, types.NewCoins(types.NewInt64Coin("wack", 10000))) sig = signing2.SignatureV2{ PubKey: pub1, Data: &signing2.SingleSignatureData{ @@ -38,13 +38,18 @@ var ( Signature: []byte("dummy"), }, } + msg0 = banktypes.NewMsgSend(addr1, addr2, types.NewCoins(types.NewInt64Coin("wack", 1))) + msg1 = sdk.ServiceMsg{ + MethodName: "/cosmos.bank.v1beta1.Msg/Send", + Request: banktypes.NewMsgSend(addr1, addr2, types.NewCoins(types.NewInt64Coin("wack", 2))), + } ) func buildTestTx(t *testing.T, builder client.TxBuilder) { builder.SetMemo(memo) builder.SetGasLimit(gas) builder.SetFeeAmount(fee) - err := builder.SetMsgs(msg) + err := builder.SetMsgs(msg0, msg1) require.NoError(t, err) err = builder.SetSignatures(sig) require.NoError(t, err) @@ -75,11 +80,15 @@ func (s *TestSuite) TestCopyTx() { protoBuilder2 := s.protoCfg.NewTxBuilder() err = tx2.CopyTx(aminoBuilder.GetTx(), protoBuilder2, false) s.Require().NoError(err) - bz, err := s.protoCfg.TxEncoder()(protoBuilder.GetTx()) + // Check sigs, signers and msgs. + sigsV2_1, err := protoBuilder.GetTx().GetSignaturesV2() s.Require().NoError(err) - bz2, err := s.protoCfg.TxEncoder()(protoBuilder2.GetTx()) + sigsV2_2, err := protoBuilder2.GetTx().GetSignaturesV2() s.Require().NoError(err) - s.Require().Equal(bz, bz2) + s.Require().Equal(sigsV2_1, sigsV2_2) + s.Require().Equal(protoBuilder.GetTx().GetSigners(), protoBuilder2.GetTx().GetSigners()) + s.Require().Equal(protoBuilder.GetTx().GetMsgs()[0], protoBuilder2.GetTx().GetMsgs()[0]) + s.Require().Equal(protoBuilder.GetTx().GetMsgs()[1].(sdk.ServiceMsg).Request, protoBuilder2.GetTx().GetMsgs()[1]) // We lose the "ServiceMsg" information // amino -> proto -> amino aminoBuilder = s.aminoCfg.NewTxBuilder() @@ -90,11 +99,15 @@ func (s *TestSuite) TestCopyTx() { aminoBuilder2 := s.aminoCfg.NewTxBuilder() err = tx2.CopyTx(protoBuilder.GetTx(), aminoBuilder2, false) s.Require().NoError(err) - bz, err = s.aminoCfg.TxEncoder()(aminoBuilder.GetTx()) + // Check sigs, signers, and msgs + sigsV2_1, err = aminoBuilder.GetTx().GetSignaturesV2() s.Require().NoError(err) - bz2, err = s.aminoCfg.TxEncoder()(aminoBuilder2.GetTx()) + sigsV2_2, err = aminoBuilder2.GetTx().GetSignaturesV2() s.Require().NoError(err) - s.Require().Equal(bz, bz2) + s.Require().Equal(sigsV2_1, sigsV2_2) + s.Require().Equal(aminoBuilder.GetTx().GetSigners(), aminoBuilder2.GetTx().GetSigners()) + s.Require().Equal(aminoBuilder.GetTx().GetMsgs()[0], aminoBuilder2.GetTx().GetMsgs()[0]) + s.Require().Equal(aminoBuilder.GetTx().GetMsgs()[1], aminoBuilder2.GetTx().GetMsgs()[1]) // We lose the "ServiceMsg" information } func (s *TestSuite) TestConvertTxToStdTx() { @@ -106,7 +119,8 @@ func (s *TestSuite) TestConvertTxToStdTx() { s.Require().Equal(memo, stdTx.Memo) s.Require().Equal(gas, stdTx.Fee.Gas) s.Require().Equal(fee, stdTx.Fee.Amount) - s.Require().Equal(msg, stdTx.Msgs[0]) + s.Require().Equal(msg0, stdTx.Msgs[0]) + s.Require().Equal(msg1.Request, stdTx.Msgs[1]) s.Require().Equal(timeoutHeight, stdTx.TimeoutHeight) s.Require().Equal(sig.PubKey, stdTx.Signatures[0].PubKey) s.Require().Equal(sig.Data.(*signing2.SingleSignatureData).Signature, stdTx.Signatures[0].Signature) @@ -125,7 +139,8 @@ func (s *TestSuite) TestConvertTxToStdTx() { s.Require().Equal(memo, stdTx.Memo) s.Require().Equal(gas, stdTx.Fee.Gas) s.Require().Equal(fee, stdTx.Fee.Amount) - s.Require().Equal(msg, stdTx.Msgs[0]) + s.Require().Equal(msg0, stdTx.Msgs[0]) + s.Require().Equal(msg1.Request, stdTx.Msgs[1]) s.Require().Equal(timeoutHeight, stdTx.TimeoutHeight) s.Require().Empty(stdTx.Signatures) @@ -158,3 +173,7 @@ func (s *TestSuite) TestConvertAndEncodeStdTx() { s.Require().NoError(err) s.Require().Equal(stdTx, decodedTx) } + +func TestTestSuite(t *testing.T) { + suite.Run(t, new(TestSuite)) +} diff --git a/docs/core/events.md b/docs/core/events.md index 87bf87066133..d199d94ced52 100644 --- a/docs/core/events.md +++ b/docs/core/events.md @@ -19,7 +19,7 @@ take the form of: `{eventType}.{eventAttribute}={value}`. Events contain: -- A `type`, which is meant to categorize an event at a high-level (e.g. by module or action). +- A `type`, which is meant to categorize an event at a high-level (e.g. by module (e.g. `module=bank`) or action (e.g. `action=/cosmos.bank.v1beta1.Msg/Send`)). - A list of `attributes`, which are key-value pairs that give more information about the categorized `event`. +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/types/events.go#L51-L56 diff --git a/server/grpc/server_test.go b/server/grpc/server_test.go index 5750b9e2e2b7..6766d9c97ce5 100644 --- a/server/grpc/server_test.go +++ b/server/grpc/server_test.go @@ -13,15 +13,13 @@ import ( "google.golang.org/grpc/metadata" rpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" - clienttx "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/testutil/network" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" grpctypes "github.com/cosmos/cosmos-sdk/types/grpc" "github.com/cosmos/cosmos-sdk/types/tx" txtypes "github.com/cosmos/cosmos-sdk/types/tx" - "github.com/cosmos/cosmos-sdk/types/tx/signing" - authclient "github.com/cosmos/cosmos-sdk/x/auth/client" + banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -37,6 +35,7 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") s.cfg = network.DefaultConfig() + s.cfg.NumValidators = 1 s.network = network.New(s.T(), s.cfg) s.Require().NotNil(s.network) @@ -130,42 +129,9 @@ func (s *IntegrationTestSuite) TestGRPCServer_GetTxsEvent() { func (s *IntegrationTestSuite) TestGRPCServer_BroadcastTx() { val0 := s.network.Validators[0] - // prepare txBuilder with msg - txBuilder := val0.ClientCtx.TxConfig.NewTxBuilder() - feeAmount := sdk.Coins{sdk.NewInt64Coin(s.cfg.BondDenom, 10)} - gasLimit := testdata.NewTestGasLimit() - s.Require().NoError( - txBuilder.SetMsgs(&banktypes.MsgSend{ - FromAddress: val0.Address.String(), - ToAddress: val0.Address.String(), - Amount: sdk.Coins{sdk.NewInt64Coin(s.cfg.BondDenom, 10)}, - }), - ) - txBuilder.SetFeeAmount(feeAmount) - txBuilder.SetGasLimit(gasLimit) - - // setup txFactory - txFactory := clienttx.Factory{}. - WithChainID(val0.ClientCtx.ChainID). - WithKeybase(val0.ClientCtx.Keyring). - WithTxConfig(val0.ClientCtx.TxConfig). - WithSignMode(signing.SignMode_SIGN_MODE_DIRECT) - - // Sign Tx. - err := authclient.SignTx(txFactory, val0.ClientCtx, val0.Moniker, txBuilder, false, true) - s.Require().NoError(err) - - txBytes, err := val0.ClientCtx.TxConfig.TxEncoder()(txBuilder.GetTx()) - s.Require().NoError(err) - - // Broadcast the tx via gRPC. - queryClient := tx.NewServiceClient(s.conn) - grpcRes, err := queryClient.BroadcastTx( - context.Background(), - &tx.BroadcastTxRequest{ - Mode: tx.BroadcastMode_BROADCAST_MODE_SYNC, - TxBytes: txBytes, - }, + grpcRes, err := banktestutil.LegacyGRPCProtoMsgSend(val0.ClientCtx, + val0.Moniker, val0.Address, val0.Address, + sdk.Coins{sdk.NewInt64Coin(s.cfg.BondDenom, 10)}, sdk.Coins{sdk.NewInt64Coin(s.cfg.BondDenom, 10)}, ) s.Require().NoError(err) s.Require().Equal(uint32(0), grpcRes.TxResponse.Code) diff --git a/types/service_msg.go b/types/service_msg.go index 61c0f15ab12a..ee6cede2eb16 100644 --- a/types/service_msg.go +++ b/types/service_msg.go @@ -1,6 +1,8 @@ package types import ( + "fmt" + "github.com/gogo/protobuf/proto" ) @@ -18,7 +20,7 @@ type MsgRequest interface { } // ServiceMsg is the struct into which an Any whose typeUrl matches a service -// method format (ex. `/cosmos.gov.Msg/SubmitProposal`) unpacks. +// method format (ex. `/cosmos.gov.v1beta1.Msg/SubmitProposal`) unpacks. type ServiceMsg struct { // MethodName is the fully-qualified service method name. MethodName string @@ -44,7 +46,17 @@ func (msg ServiceMsg) ValidateBasic() error { // GetSignBytes implements Msg.GetSignBytes method. func (msg ServiceMsg) GetSignBytes() []byte { - panic("ServiceMsg does not have a GetSignBytes method") + // Here, we're gracefully supporting Amino JSON for service + // Msgs. + // ref: https://github.com/cosmos/cosmos-sdk/issues/8346 + // If `msg` is a service Msg, then we cast its `Request` to a sdk.Msg + // and call GetSignBytes on the `Request`. + msgRequest, ok := msg.Request.(Msg) + if !ok { + panic(fmt.Errorf("cannot convert ServiceMsg request to sdk.Msg, got %T", msgRequest)) + } + + return msgRequest.GetSignBytes() } // GetSigners implements Msg.GetSigners method. diff --git a/x/auth/client/cli/cli_test.go b/x/auth/client/cli/cli_test.go index d8913d1ac07e..efc7fbee9459 100644 --- a/x/auth/client/cli/cli_test.go +++ b/x/auth/client/cli/cli_test.go @@ -230,23 +230,19 @@ func (s *IntegrationTestSuite) TestCLIQueryTxCmd() { sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10) // Send coins, try both with legacy Msg and with Msg service. - // Legacy Msg. - legacyMsgOut, err := bankcli.MsgSendExec( - val.ClientCtx, + // Legacy proto Msg. + legacyTxRes, err := bankcli.LegacyGRPCProtoMsgSend( + val.ClientCtx, val.Moniker, val.Address, account2.GetAddress(), + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))), sdk.NewCoins(sendTokens), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), - fmt.Sprintf("--gas=%d", flags.DefaultGasLimit), ) s.Require().NoError(err) - var legacyMsgTxRes sdk.TxResponse - s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(legacyMsgOut.Bytes(), &legacyMsgTxRes)) + s.Require().NoError(s.network.WaitForNextBlock()) // Service Msg. - out, err := bankcli.ServiceMsgSendExec( + out, err := bankcli.MsgSendExec( val.ClientCtx, val.Address, account2.GetAddress(), @@ -259,7 +255,6 @@ func (s *IntegrationTestSuite) TestCLIQueryTxCmd() { s.Require().NoError(err) var txRes sdk.TxResponse s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &txRes)) - s.Require().NoError(s.network.WaitForNextBlock()) testCases := []struct { @@ -282,7 +277,7 @@ func (s *IntegrationTestSuite) TestCLIQueryTxCmd() { }, { "happy case (legacy Msg)", - []string{legacyMsgTxRes.TxHash, fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + []string{legacyTxRes.TxResponse.TxHash, fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, false, "", }, diff --git a/x/auth/client/rest/rest_test.go b/x/auth/client/rest/rest_test.go index 1196e52e4a68..b78acd2c8a9a 100644 --- a/x/auth/client/rest/rest_test.go +++ b/x/auth/client/rest/rest_test.go @@ -269,7 +269,7 @@ func (s *IntegrationTestSuite) TestQueryTxWithStdTx() { s.testQueryTx(s.stdTxRes.Height, s.stdTxRes.TxHash, val0.Address.String()) } -func (s *IntegrationTestSuite) TestQueryTxWithServiceMessage() { +func (s *IntegrationTestSuite) TestQueryTxWithServiceMsg() { val := s.network.Validators[0] sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10) @@ -278,7 +278,7 @@ func (s *IntegrationTestSuite) TestQueryTxWithServiceMessage() { // Might need to wait a block to refresh sequences from previous setups. s.Require().NoError(s.network.WaitForNextBlock()) - out, err := bankcli.ServiceMsgSendExec( + out, err := bankcli.MsgSendExec( val.ClientCtx, val.Address, addr, diff --git a/x/auth/legacy/legacytx/stdsign.go b/x/auth/legacy/legacytx/stdsign.go index 2ba194dad843..466981369624 100644 --- a/x/auth/legacy/legacytx/stdsign.go +++ b/x/auth/legacy/legacytx/stdsign.go @@ -35,6 +35,9 @@ type StdSignDoc struct { func StdSignBytes(chainID string, accnum, sequence, timeout uint64, fee StdFee, msgs []sdk.Msg, memo string) []byte { msgsBytes := make([]json.RawMessage, 0, len(msgs)) for _, msg := range msgs { + // If msg is a legacy Msg, then GetSignBytes is implemented. + // If msg is a ServiceMsg, then GetSignBytes has graceful support of + // calling GetSignBytes from its underlying Msg. msgsBytes = append(msgsBytes, json.RawMessage(msg.GetSignBytes())) } diff --git a/x/auth/tx/service_test.go b/x/auth/tx/service_test.go index b7b3322dc33f..4f5db8e9c99d 100644 --- a/x/auth/tx/service_test.go +++ b/x/auth/tx/service_test.go @@ -175,14 +175,14 @@ func (s IntegrationTestSuite) TestGetTxEvents_GRPC() { { "without pagination", &tx.GetTxsEventRequest{ - Events: []string{"message.action=send"}, + Events: []string{"message.action=/cosmos.bank.v1beta1.Msg/Send"}, }, false, "", }, { "with pagination", &tx.GetTxsEventRequest{ - Events: []string{"message.action=send"}, + Events: []string{"message.action=/cosmos.bank.v1beta1.Msg/Send"}, Pagination: &query.PageRequest{ CountTotal: false, Offset: 0, @@ -194,7 +194,7 @@ func (s IntegrationTestSuite) TestGetTxEvents_GRPC() { { "with multi events", &tx.GetTxsEventRequest{ - Events: []string{"message.action=send", "message.module=bank"}, + Events: []string{"message.action=/cosmos.bank.v1beta1.Msg/Send", "message.module=bank"}, }, false, "", }, @@ -231,25 +231,25 @@ func (s IntegrationTestSuite) TestGetTxEvents_GRPCGateway() { }, { "without pagination", - fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s", val.APIAddress, "message.action=send"), + fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s", val.APIAddress, "message.action=/cosmos.bank.v1beta1.Msg/Send"), false, "", }, { "with pagination", - fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&pagination.offset=%d&pagination.limit=%d", val.APIAddress, "message.action=send", 0, 10), + fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&pagination.offset=%d&pagination.limit=%d", val.APIAddress, "message.action=/cosmos.bank.v1beta1.Msg/Send", 0, 10), false, "", }, { "expect pass with multiple-events", - fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&events=%s", val.APIAddress, "message.action=send", "message.module=bank"), + fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&events=%s", val.APIAddress, "message.action=/cosmos.bank.v1beta1.Msg/Send", "message.module=bank"), false, "", }, { "expect pass with escape event", - fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s", val.APIAddress, "message.action%3Dsend"), + fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s", val.APIAddress, "message.action%3D%2Fcosmos.bank.v1beta1.Msg%2FSend"), false, "", }, diff --git a/x/auth/vesting/client/cli/tx.go b/x/auth/vesting/client/cli/tx.go index 9cacdfdaab25..c6c2ac1432d2 100644 --- a/x/auth/vesting/client/cli/tx.go +++ b/x/auth/vesting/client/cli/tx.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" ) @@ -69,11 +70,14 @@ timestamp.`, delayed, _ := cmd.Flags().GetBool(FlagDelayed) msg := types.NewMsgCreateVestingAccount(clientCtx.GetFromAddress(), toAddr, amount, endTime, delayed) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.CreateVestingAccount(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } diff --git a/x/authz/client/cli/cli_test.go b/x/authz/client/cli/cli_test.go index 96f5da08bbcf..4ad3d93f3d1e 100644 --- a/x/authz/client/cli/cli_test.go +++ b/x/authz/client/cli/cli_test.go @@ -647,7 +647,7 @@ func (s *IntegrationTestSuite) TestNewExecGrantAuthorized() { tokens := sdk.NewCoins( sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), sdk.NewInt(12)), ) - normalGeneratedTx, err := bankcli.ServiceMsgSendExec( + normalGeneratedTx, err := bankcli.MsgSendExec( val.ClientCtx, val.Address, grantee, diff --git a/x/authz/client/cli/tx.go b/x/authz/client/cli/tx.go index ba2fd210124b..81540ef1f58b 100644 --- a/x/authz/client/cli/tx.go +++ b/x/authz/client/cli/tx.go @@ -108,8 +108,8 @@ Examples: } svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - authzMsgClient := types.NewMsgClient(svcMsgClientConn) - _, err = authzMsgClient.GrantAuthorization(context.Background(), msg) + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.GrantAuthorization(context.Background(), msg) if err != nil { return err } @@ -153,8 +153,8 @@ Example: msg := types.NewMsgRevokeAuthorization(granter, grantee, msgAuthorized) svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - authzMsgClient := types.NewMsgClient(svcMsgClientConn) - _, err = authzMsgClient.RevokeAuthorization(context.Background(), &msg) + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.RevokeAuthorization(context.Background(), &msg) if err != nil { return err } @@ -206,8 +206,8 @@ Example: msg := types.NewMsgExecAuthorized(grantee, serviceMsgs) svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - authzMsgClient := types.NewMsgClient(svcMsgClientConn) - _, err = authzMsgClient.ExecAuthorized(context.Background(), &msg) + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.ExecAuthorized(context.Background(), &msg) if err != nil { return err } diff --git a/x/bank/client/cli/cli_test.go b/x/bank/client/cli/cli_test.go index 952390fe774b..98127101be7a 100644 --- a/x/bank/client/cli/cli_test.go +++ b/x/bank/client/cli/cli_test.go @@ -372,7 +372,10 @@ func (s *IntegrationTestSuite) TestNewSendTxCmdGenOnly() { s.Require().NoError(err) tx, err := s.cfg.TxConfig.TxJSONDecoder()(bz.Bytes()) s.Require().NoError(err) - s.Require().Equal([]sdk.Msg{types.NewMsgSend(from, to, amount)}, tx.GetMsgs()) + s.Require().Equal([]sdk.Msg{sdk.ServiceMsg{ + MethodName: "/cosmos.bank.v1beta1.Msg/Send", + Request: types.NewMsgSend(from, to, amount), + }}, tx.GetMsgs()) } func (s *IntegrationTestSuite) TestNewSendTxCmd() { @@ -461,61 +464,6 @@ func (s *IntegrationTestSuite) TestNewSendTxCmd() { } } -// TestBankMsgService does a basic test of whether or not service Msg's as defined -// in ADR 031 work in the most basic end-to-end case. -func (s *IntegrationTestSuite) TestBankMsgService() { - val := s.network.Validators[0] - - testCases := []struct { - name string - from, to sdk.AccAddress - amount sdk.Coins - args []string - expectErr bool - respType proto.Message - expectedCode uint32 - rawLogContains string - }{ - { - "valid transaction", - val.Address, - val.Address, - sdk.NewCoins( - sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), sdk.NewInt(10)), - sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)), - ), - []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), - }, - false, - &sdk.TxResponse{}, - 0, - "/cosmos.bank.v1beta1.Msg/Send", // indicates we are using ServiceMsg and not a regular Msg - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - clientCtx := val.ClientCtx - bz, err := banktestutil.ServiceMsgSendExec(clientCtx, tc.from, tc.to, tc.amount, tc.args...) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - - s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(bz.Bytes(), tc.respType), bz.String()) - txResp := tc.respType.(*sdk.TxResponse) - s.Require().Equal(tc.expectedCode, txResp.Code) - s.Require().Contains(txResp.RawLog, tc.rawLogContains) - } - }) - } -} - func TestIntegrationTestSuite(t *testing.T) { suite.Run(t, new(IntegrationTestSuite)) } diff --git a/x/bank/client/cli/tx.go b/x/bank/client/cli/tx.go index d88a95fc6c09..4a615d5045ca 100644 --- a/x/bank/client/cli/tx.go +++ b/x/bank/client/cli/tx.go @@ -7,6 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -49,11 +50,14 @@ ignored as it is implied from [from_key_or_address].`, } msg := types.NewMsgSend(clientCtx.GetFromAddress(), toAddr, coins) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.Send(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } diff --git a/x/bank/client/testutil/cli_helpers.go b/x/bank/client/testutil/cli_helpers.go index e36f3744a6b9..57a5a5798edc 100644 --- a/x/bank/client/testutil/cli_helpers.go +++ b/x/bank/client/testutil/cli_helpers.go @@ -1,18 +1,20 @@ package testutil import ( + "context" "fmt" - "github.com/spf13/cobra" "github.com/tendermint/tendermint/libs/cli" "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/testutil" clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/msgservice" + txtypes "github.com/cosmos/cosmos-sdk/types/tx" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + authclient "github.com/cosmos/cosmos-sdk/x/auth/client" bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/cli" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -31,54 +33,55 @@ func QueryBalancesExec(clientCtx client.Context, address fmt.Stringer, extraArgs return clitestutil.ExecTestCLICmd(clientCtx, bankcli.GetBalancesCmd(), args) } -// newSendTxMsgServiceCmd is just for the purpose of testing ServiceMsg's in an end-to-end case. It is effectively -// NewSendTxCmd but using MsgClient. -func newSendTxMsgServiceCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "send [from_key_or_address] [to_address] [amount]", - Short: `Send funds from one account to another. Note, the'--from' flag is -ignored as it is implied from [from_key_or_address].`, - Args: cobra.ExactArgs(3), - RunE: func(cmd *cobra.Command, args []string) error { - cmd.Flags().Set(flags.FlagFrom, args[0]) - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - toAddr, err := sdk.AccAddressFromBech32(args[1]) - if err != nil { - return err - } +// LegacyGRPCProtoMsgSend is a legacy method to broadcast a legacy proto MsgSend. +// +// Deprecated. +//nolint:interfacer +func LegacyGRPCProtoMsgSend(clientCtx client.Context, keyName string, from, to sdk.Address, fee, amount []sdk.Coin, extraArgs ...string) (*txtypes.BroadcastTxResponse, error) { + // prepare txBuilder with msg + txBuilder := clientCtx.TxConfig.NewTxBuilder() + feeAmount := fee + gasLimit := testdata.NewTestGasLimit() - coins, err := sdk.ParseCoinsNormalized(args[2]) - if err != nil { - return err - } + // This sets a legacy Proto MsgSend. + err := txBuilder.SetMsgs(&types.MsgSend{ + FromAddress: from.String(), + ToAddress: to.String(), + Amount: amount, + }) + if err != nil { + return nil, err + } - msg := types.NewMsgSend(clientCtx.GetFromAddress(), toAddr, coins) - svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - bankMsgClient := types.NewMsgClient(svcMsgClientConn) - _, err = bankMsgClient.Send(cmd.Context(), msg) - if err != nil { - return err - } + txBuilder.SetFeeAmount(feeAmount) + txBuilder.SetGasLimit(gasLimit) - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) - }, - } + // setup txFactory + txFactory := tx.Factory{}. + WithChainID(clientCtx.ChainID). + WithKeybase(clientCtx.Keyring). + WithTxConfig(clientCtx.TxConfig). + WithSignMode(signing.SignMode_SIGN_MODE_DIRECT) - flags.AddTxFlagsToCmd(cmd) + // Sign Tx. + err = authclient.SignTx(txFactory, clientCtx, keyName, txBuilder, false, true) + if err != nil { + return nil, err + } - return cmd -} + txBytes, err := clientCtx.TxConfig.TxEncoder()(txBuilder.GetTx()) + if err != nil { + return nil, err + } -// ServiceMsgSendExec is a temporary method to test Msg services in CLI using -// x/bank's Msg/Send service. After https://github.com/cosmos/cosmos-sdk/issues/7541 -// is merged, this method should be removed, and we should prefer MsgSendExec -// instead. -func ServiceMsgSendExec(clientCtx client.Context, from, to, amount fmt.Stringer, extraArgs ...string) (testutil.BufferWriter, error) { - args := []string{from.String(), to.String(), amount.String()} - args = append(args, extraArgs...) + // Broadcast the tx via gRPC. + queryClient := txtypes.NewServiceClient(clientCtx) - return clitestutil.ExecTestCLICmd(clientCtx, newSendTxMsgServiceCmd(), args) + return queryClient.BroadcastTx( + context.Background(), + &txtypes.BroadcastTxRequest{ + Mode: txtypes.BroadcastMode_BROADCAST_MODE_SYNC, + TxBytes: txBytes, + }, + ) } diff --git a/x/crisis/client/cli/tx.go b/x/crisis/client/cli/tx.go index c18231724ee3..c1288b95ed27 100644 --- a/x/crisis/client/cli/tx.go +++ b/x/crisis/client/cli/tx.go @@ -8,6 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/x/crisis/types" ) @@ -49,11 +50,14 @@ func NewMsgVerifyInvariantTxCmd() *cobra.Command { senderAddr := clientCtx.GetFromAddress() msg := types.NewMsgVerifyInvariant(senderAddr, moduleName, route) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.VerifyInvariant(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go index dcf5a3b057ad..6237bf92ef5e 100644 --- a/x/distribution/client/cli/tx.go +++ b/x/distribution/client/cli/tx.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/distribution/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" @@ -214,11 +215,14 @@ $ %s tx distribution set-withdraw-addr %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p } msg := types.NewMsgSetWithdrawAddress(delAddr, withdrawAddr) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.SetWithdrawAddress(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } @@ -253,11 +257,14 @@ $ %s tx distribution fund-community-pool 100uatom --from mykey } msg := types.NewMsgFundCommunityPool(amount, depositorAddr) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.FundCommunityPool(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } @@ -326,11 +333,14 @@ Where proposal.json contains: return err } - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := govtypes.NewMsgClient(svcMsgClientConn) + _, err = msgClient.SubmitProposal(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } diff --git a/x/feegrant/client/cli/tx.go b/x/feegrant/client/cli/tx.go index a28ddb976cc1..49702e0c7882 100644 --- a/x/feegrant/client/cli/tx.go +++ b/x/feegrant/client/cli/tx.go @@ -149,8 +149,8 @@ Examples: } svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - feeGrantMsgClient := types.NewMsgClient(svcMsgClientConn) - _, err = feeGrantMsgClient.GrantFeeAllowance(cmd.Context(), msg) + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.GrantFeeAllowance(cmd.Context(), msg) if err != nil { return err } @@ -196,8 +196,8 @@ Example: msg := types.NewMsgRevokeFeeAllowance(clientCtx.GetFromAddress(), grantee) svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - feeGrantMsgClient := types.NewMsgClient(svcMsgClientConn) - _, err = feeGrantMsgClient.RevokeFeeAllowance(cmd.Context(), &msg) + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.RevokeFeeAllowance(cmd.Context(), &msg) if err != nil { return err } diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 09aa6e5315a8..8ea8f00238bf 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/version" govutils "github.com/cosmos/cosmos-sdk/x/gov/client/utils" "github.com/cosmos/cosmos-sdk/x/gov/types" @@ -126,11 +127,14 @@ $ %s tx gov submit-proposal --title="Test Proposal" --description="My awesome pr return fmt.Errorf("invalid message: %w", err) } - if err = msg.ValidateBasic(); err != nil { - return fmt.Errorf("message validation failed: %w", err) + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.SubmitProposal(cmd.Context(), msg) + if err != nil { + return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } @@ -182,12 +186,14 @@ $ %s tx gov deposit 1 10stake --from mykey } msg := types.NewMsgDeposit(from, proposalID, amount) - err = msg.ValidateBasic() + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.Deposit(cmd.Context(), msg) if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } @@ -234,12 +240,14 @@ $ %s tx gov vote 1 yes --from mykey // Build vote message and run basic validation msg := types.NewMsgVote(from, proposalID, byteVoteOption) - err = msg.ValidateBasic() + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.Vote(cmd.Context(), msg) if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } diff --git a/x/gov/client/utils/query.go b/x/gov/client/utils/query.go index 5e4cead6cf6e..de5f5f7c5e47 100644 --- a/x/gov/client/utils/query.go +++ b/x/gov/client/utils/query.go @@ -37,14 +37,19 @@ func (p Proposer) String() string { // NOTE: SearchTxs is used to facilitate the txs query which does not currently // support configurable pagination. func QueryDepositsByTxQuery(clientCtx client.Context, params types.QueryProposalParams) ([]byte, error) { - events := []string{ - fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgDeposit), - fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalDeposit, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), - } - - // NOTE: SearchTxs is used to facilitate the txs query which does not currently - // support configurable pagination. - searchResult, err := authclient.QueryTxsByEvents(clientCtx, events, defaultPage, defaultLimit, "") + searchResult, err := combineEvents( + clientCtx, defaultPage, + // Query old Msgs + []string{ + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgDeposit), + fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalDeposit, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), + }, + // Query service Msgs + []string{ + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeSvcMsgDeposit), + fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalDeposit, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), + }, + ) if err != nil { return nil, err } @@ -53,9 +58,14 @@ func QueryDepositsByTxQuery(clientCtx client.Context, params types.QueryProposal for _, info := range searchResult.Txs { for _, msg := range info.GetTx().GetMsgs() { - if msg.Type() == types.TypeMsgDeposit { - depMsg := msg.(*types.MsgDeposit) + var depMsg *types.MsgDeposit + if msg.Type() == types.TypeSvcMsgDeposit { + depMsg = msg.(sdk.ServiceMsg).Request.(*types.MsgDeposit) + } else if protoDepMsg, ok := msg.(*types.MsgDeposit); ok { + depMsg = protoDepMsg + } + if depMsg != nil { deposits = append(deposits, types.Deposit{ Depositor: depMsg.Depositor, ProposalId: params.ProposalID, @@ -78,39 +88,70 @@ func QueryDepositsByTxQuery(clientCtx client.Context, params types.QueryProposal // marshalled result or any error that occurred. func QueryVotesByTxQuery(clientCtx client.Context, params types.QueryProposalVotesParams) ([]byte, error) { var ( - events = []string{ - fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgVote), - fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgVoteWeighted), - fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), - } votes []types.Vote nextTxPage = defaultPage totalLimit = params.Limit * params.Page ) + // query interrupted either if we collected enough votes or tx indexer run out of relevant txs for len(votes) < totalLimit { - searchResult, err := authclient.QueryTxsByEvents(clientCtx, events, nextTxPage, defaultLimit, "") + // Search for both (old) votes and weighted votes. + searchResult, err := combineEvents( + clientCtx, nextTxPage, + // Query old Vote Msgs + []string{ + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgVote), + fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), + }, + // Query Vote service Msgs + []string{ + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeSvcMsgVote), + fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), + }, + // Query old VoteWeighted Msgs + []string{ + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgVoteWeighted), + fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), + }, + // Query VoteWeighted service Msgs + []string{ + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeSvcMsgVoteWeighted), + fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), + }, + ) if err != nil { return nil, err } - nextTxPage++ + for _, info := range searchResult.Txs { for _, msg := range info.GetTx().GetMsgs() { - if msg.Type() == types.TypeMsgVote { - voteMsg := msg.(*types.MsgVote) + var voteMsg *types.MsgVote + if msg.Type() == types.TypeSvcMsgVote { + voteMsg = msg.(sdk.ServiceMsg).Request.(*types.MsgVote) + } else if protoVoteMsg, ok := msg.(*types.MsgVote); ok { + voteMsg = protoVoteMsg + } + if voteMsg != nil { votes = append(votes, types.Vote{ Voter: voteMsg.Voter, ProposalId: params.ProposalID, Options: types.NewNonSplitVoteOption(voteMsg.Option), }) - } else if msg.Type() == types.TypeMsgVoteWeighted { - voteMsg := msg.(*types.MsgVoteWeighted) + } + + var voteWeightedMsg *types.MsgVoteWeighted + if msg.Type() == types.TypeSvcMsgVoteWeighted { + voteWeightedMsg = msg.(sdk.ServiceMsg).Request.(*types.MsgVoteWeighted) + } else if protoVoteWeightedMsg, ok := msg.(*types.MsgVoteWeighted); ok { + voteWeightedMsg = protoVoteWeightedMsg + } + if voteWeightedMsg != nil { votes = append(votes, types.Vote{ - Voter: voteMsg.Voter, + Voter: voteWeightedMsg.Voter, ProposalId: params.ProposalID, - Options: voteMsg.Options, + Options: voteWeightedMsg.Options, }) } } @@ -118,6 +159,8 @@ func QueryVotesByTxQuery(clientCtx client.Context, params types.QueryProposalVot if len(searchResult.Txs) != defaultLimit { break } + + nextTxPage++ } start, end := client.Paginate(len(votes), params.Page, params.Limit, 100) if start < 0 || end < 0 { @@ -136,24 +179,48 @@ func QueryVotesByTxQuery(clientCtx client.Context, params types.QueryProposalVot // QueryVoteByTxQuery will query for a single vote via a direct txs tags query. func QueryVoteByTxQuery(clientCtx client.Context, params types.QueryVoteParams) ([]byte, error) { - events := []string{ - fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgVote), - fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), - fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, []byte(params.Voter.String())), - } - - // NOTE: SearchTxs is used to facilitate the txs query which does not currently - // support configurable pagination. - searchResult, err := authclient.QueryTxsByEvents(clientCtx, events, defaultPage, defaultLimit, "") + searchResult, err := combineEvents( + clientCtx, defaultPage, + // Query old Vote Msgs + []string{ + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgVote), + fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, []byte(params.Voter.String())), + }, + // Query Vote service Msgs + []string{ + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeSvcMsgVote), + fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, []byte(params.Voter.String())), + }, + // Query old VoteWeighted Msgs + []string{ + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgVoteWeighted), + fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, []byte(params.Voter.String())), + }, + // Query VoteWeighted service Msgs + []string{ + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeSvcMsgVoteWeighted), + fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, []byte(params.Voter.String())), + }, + ) if err != nil { return nil, err } + for _, info := range searchResult.Txs { for _, msg := range info.GetTx().GetMsgs() { + var voteMsg *types.MsgVote // there should only be a single vote under the given conditions - if msg.Type() == types.TypeMsgVote { - voteMsg := msg.(*types.MsgVote) + if msg.Type() == types.TypeSvcMsgVote { + voteMsg = msg.(sdk.ServiceMsg).Request.(*types.MsgVote) + } else if protoVoteMsg, ok := msg.(*types.MsgVote); ok { + voteMsg = protoVoteMsg + } + if voteMsg != nil { vote := types.Vote{ Voter: voteMsg.Voter, ProposalId: params.ProposalID, @@ -191,25 +258,36 @@ func QueryVoteByTxQuery(clientCtx client.Context, params types.QueryVoteParams) // QueryDepositByTxQuery will query for a single deposit via a direct txs tags // query. func QueryDepositByTxQuery(clientCtx client.Context, params types.QueryDepositParams) ([]byte, error) { - events := []string{ - fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgDeposit), - fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalDeposit, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), - fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, []byte(params.Depositor.String())), - } - - // NOTE: SearchTxs is used to facilitate the txs query which does not currently - // support configurable pagination. - searchResult, err := authclient.QueryTxsByEvents(clientCtx, events, defaultPage, defaultLimit, "") + searchResult, err := combineEvents( + clientCtx, defaultPage, + // Query old Msgs + []string{ + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgDeposit), + fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalDeposit, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, []byte(params.Depositor.String())), + }, + // Query service Msgs + []string{ + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeSvcMsgDeposit), + fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalDeposit, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))), + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, []byte(params.Depositor.String())), + }, + ) if err != nil { return nil, err } for _, info := range searchResult.Txs { for _, msg := range info.GetTx().GetMsgs() { + var depMsg *types.MsgDeposit // there should only be a single deposit under the given conditions - if msg.Type() == types.TypeMsgDeposit { - depMsg := msg.(*types.MsgDeposit) + if msg.Type() == types.TypeSvcMsgDeposit { + depMsg = msg.(sdk.ServiceMsg).Request.(*types.MsgDeposit) + } else if protoDepMsg, ok := msg.(*types.MsgDeposit); ok { + depMsg = protoDepMsg + } + if depMsg != nil { deposit := types.Deposit{ Depositor: depMsg.Depositor, ProposalId: params.ProposalID, @@ -232,14 +310,20 @@ func QueryDepositByTxQuery(clientCtx client.Context, params types.QueryDepositPa // QueryProposerByTxQuery will query for a proposer of a governance proposal by // ID. func QueryProposerByTxQuery(clientCtx client.Context, proposalID uint64) (Proposer, error) { - events := []string{ - fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgSubmitProposal), - fmt.Sprintf("%s.%s='%s'", types.EventTypeSubmitProposal, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", proposalID))), - } - - // NOTE: SearchTxs is used to facilitate the txs query which does not currently - // support configurable pagination. - searchResult, err := authclient.QueryTxsByEvents(clientCtx, events, defaultPage, defaultLimit, "") + searchResult, err := combineEvents( + clientCtx, + defaultPage, + // Query old Msgs + []string{ + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgSubmitProposal), + fmt.Sprintf("%s.%s='%s'", types.EventTypeSubmitProposal, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", proposalID))), + }, + // Query service Msgs + []string{ + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeSvcMsgSubmitProposal), + fmt.Sprintf("%s.%s='%s'", types.EventTypeSubmitProposal, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", proposalID))), + }, + ) if err != nil { return Proposer{}, err } @@ -247,8 +331,13 @@ func QueryProposerByTxQuery(clientCtx client.Context, proposalID uint64) (Propos for _, info := range searchResult.Txs { for _, msg := range info.GetTx().GetMsgs() { // there should only be a single proposal under the given conditions - if msg.Type() == types.TypeMsgSubmitProposal { - subMsg := msg.(*types.MsgSubmitProposal) + if msg.Type() == types.TypeSvcMsgSubmitProposal { + subMsg := msg.(sdk.ServiceMsg).Request.(*types.MsgSubmitProposal) + + return NewProposer(proposalID, subMsg.Proposer), nil + } else if protoSubMsg, ok := msg.(*types.MsgSubmitProposal); ok { + subMsg := protoSubMsg + return NewProposer(proposalID, subMsg.Proposer), nil } } @@ -272,3 +361,25 @@ func QueryProposalByID(proposalID uint64, clientCtx client.Context, queryRoute s return res, err } + +// combineEvents queries txs by events with all events from each event group, +// and combines all those events together. +// +// Tx are indexed in tendermint via their Msgs `Type()`, which can be: +// - via legacy Msgs (amino or proto), their `Type()` is a custom string, +// - via ADR-031 service msgs, their `Type()` is the protobuf FQ method name. +// In searching for events, we search for both `Type()`s, and we use the +// `combineEvents` function here to merge events. +func combineEvents(clientCtx client.Context, page int, eventGroups ...[]string) (*sdk.SearchTxsResult, error) { + // Only the Txs field will be populated in the final SearchTxsResult. + allTxs := []*sdk.TxResponse{} + for _, events := range eventGroups { + res, err := authclient.QueryTxsByEvents(clientCtx, events, page, defaultLimit, "") + if err != nil { + return nil, err + } + allTxs = append(allTxs, res.Txs...) + } + + return &sdk.SearchTxsResult{Txs: allTxs}, nil +} diff --git a/x/gov/client/utils/query_test.go b/x/gov/client/utils/query_test.go index 4a68e05dfac5..fb7d002c8583 100644 --- a/x/gov/client/utils/query_test.go +++ b/x/gov/client/utils/query_test.go @@ -2,6 +2,7 @@ package utils_test import ( "context" + "regexp" "testing" "github.com/stretchr/testify/require" @@ -10,15 +11,14 @@ import ( tmtypes "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/gov/client/utils" "github.com/cosmos/cosmos-sdk/x/gov/types" ) type TxSearchMock struct { + txConfig client.TxConfig mock.Client txs []tmtypes.Tx } @@ -32,12 +32,35 @@ func (mock TxSearchMock) TxSearch(ctx context.Context, query string, prove bool, *perPage = 0 } + // Get the `message.action` value from the query. + messageAction := regexp.MustCompile(`message\.action='(.*)' .*$`) + msgType := messageAction.FindStringSubmatch(query)[1] + + // Filter only the txs that match the query + matchingTxs := make([]tmtypes.Tx, 0) + for _, tx := range mock.txs { + sdkTx, err := mock.txConfig.TxDecoder()(tx) + if err != nil { + return nil, err + } + for _, msg := range sdkTx.GetMsgs() { + if msg.Type() == msgType { + matchingTxs = append(matchingTxs, tx) + break + } + } + } + start, end := client.Paginate(len(mock.txs), *page, *perPage, 100) if start < 0 || end < 0 { // nil result with nil error crashes utils.QueryTxsByEvents return &ctypes.ResultTxSearch{}, nil } - txs := mock.txs[start:end] + if len(matchingTxs) < end { + return &ctypes.ResultTxSearch{}, nil + } + + txs := matchingTxs[start:end] rst := &ctypes.ResultTxSearch{Txs: make([]*ctypes.ResultTx, len(txs)), TotalCount: len(txs)} for i := range txs { rst.Txs[i] = &ctypes.ResultTx{Tx: txs[i]} @@ -50,15 +73,9 @@ func (mock TxSearchMock) Block(ctx context.Context, height *int64) (*ctypes.Resu return &ctypes.ResultBlock{Block: &tmtypes.Block{}}, nil } -func newTestCodec() *codec.LegacyAmino { - cdc := codec.NewLegacyAmino() - sdk.RegisterLegacyAminoCodec(cdc) - types.RegisterLegacyAminoCodec(cdc) - authtypes.RegisterLegacyAminoCodec(cdc) - return cdc -} - func TestGetPaginatedVotes(t *testing.T) { + encCfg := simapp.MakeTestEncodingConfig() + type testCase struct { description string page, limit int @@ -144,17 +161,12 @@ func TestGetPaginatedVotes(t *testing.T) { tc := tc t.Run(tc.description, func(t *testing.T) { - var ( - marshalled = make([]tmtypes.Tx, len(tc.msgs)) - cdc = newTestCodec() - ) - - encodingConfig := simapp.MakeTestEncodingConfig() - cli := TxSearchMock{txs: marshalled} + var marshalled = make([]tmtypes.Tx, len(tc.msgs)) + cli := TxSearchMock{txs: marshalled, txConfig: encCfg.TxConfig} clientCtx := client.Context{}. - WithLegacyAmino(cdc). + WithLegacyAmino(encCfg.Amino). WithClient(cli). - WithTxConfig(encodingConfig.TxConfig) + WithTxConfig(encCfg.TxConfig) for i := range tc.msgs { txBuilder := clientCtx.TxConfig.NewTxBuilder() diff --git a/x/gov/types/msgs.go b/x/gov/types/msgs.go index f1c351e6ddca..098aad437857 100644 --- a/x/gov/types/msgs.go +++ b/x/gov/types/msgs.go @@ -18,6 +18,12 @@ const ( TypeMsgVote = "vote" TypeMsgVoteWeighted = "weighted_vote" TypeMsgSubmitProposal = "submit_proposal" + + // These are used for querying events by action. + TypeSvcMsgDeposit = "/cosmos.gov.v1beta1.Msg/Deposit" + TypeSvcMsgVote = "/cosmos.gov.v1beta1.Msg/Vote" + TypeSvcMsgVoteWeighted = "/cosmos.gov.v1beta1.Msg/VoteWeighted" + TypeSvcMsgSubmitProposal = "/cosmos.gov.v1beta1.Msg/SubmitProposal" ) var ( diff --git a/x/ibc/applications/transfer/client/cli/tx.go b/x/ibc/applications/transfer/client/cli/tx.go index c9c6fde51794..1f9e92f63cad 100644 --- a/x/ibc/applications/transfer/client/cli/tx.go +++ b/x/ibc/applications/transfer/client/cli/tx.go @@ -10,6 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" @@ -96,11 +97,14 @@ to the counterparty channel. Any timeout set to 0 is disabled.`), msg := types.NewMsgTransfer( srcPort, srcChannel, coin, sender, receiver, timeoutHeight, timeoutTimestamp, ) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.Transfer(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } diff --git a/x/ibc/core/02-client/client/cli/tx.go b/x/ibc/core/02-client/client/cli/tx.go index 78313d21b7a3..bdaa53a8ae1e 100644 --- a/x/ibc/core/02-client/client/cli/tx.go +++ b/x/ibc/core/02-client/client/cli/tx.go @@ -12,6 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/version" govcli "github.com/cosmos/cosmos-sdk/x/gov/client/cli" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" @@ -73,11 +74,14 @@ func NewCreateClientCmd() *cobra.Command { return err } - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.CreateClient(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } @@ -123,11 +127,14 @@ func NewUpdateClientCmd() *cobra.Command { return err } - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.UpdateClient(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } } @@ -168,11 +175,14 @@ func NewSubmitMisbehaviourCmd() *cobra.Command { return err } - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.SubmitMisbehaviour(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } } @@ -235,11 +245,14 @@ func NewUpgradeClientCmd() *cobra.Command { return err } - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.UpgradeClient(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } diff --git a/x/ibc/core/03-connection/client/cli/tx.go b/x/ibc/core/03-connection/client/cli/tx.go index 339e2e9770f4..68b1a6208200 100644 --- a/x/ibc/core/03-connection/client/cli/tx.go +++ b/x/ibc/core/03-connection/client/cli/tx.go @@ -12,6 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/version" clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/client/utils" @@ -76,11 +77,14 @@ func NewConnectionOpenInitCmd() *cobra.Command { counterpartyPrefix, version, delayPeriod, clientCtx.GetFromAddress(), ) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.ConnectionOpenInit(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } @@ -189,11 +193,14 @@ func NewConnectionOpenTryCmd() *cobra.Command { consensusHeight, clientCtx.GetFromAddress(), ) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.ConnectionOpenTry(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } @@ -276,11 +283,14 @@ func NewConnectionOpenAckCmd() *cobra.Command { consensusHeight, version, clientCtx.GetFromAddress(), ) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.ConnectionOpenAck(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } @@ -321,11 +331,14 @@ func NewConnectionOpenConfirmCmd() *cobra.Command { connectionID, proofAck, proofHeight, clientCtx.GetFromAddress(), ) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.ConnectionOpenConfirm(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } diff --git a/x/ibc/core/04-channel/client/cli/tx.go b/x/ibc/core/04-channel/client/cli/tx.go index 21aafba19460..20afe6226746 100644 --- a/x/ibc/core/04-channel/client/cli/tx.go +++ b/x/ibc/core/04-channel/client/cli/tx.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/types/msgservice" ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" connectionutils "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/client/utils" @@ -42,11 +43,14 @@ func NewChannelOpenInitCmd() *cobra.Command { portID, version, order, hops, counterpartyPortID, clientCtx.GetFromAddress(), ) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.ChannelOpenInit(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } @@ -93,11 +97,14 @@ func NewChannelOpenTryCmd() *cobra.Command { counterpartyPortID, counterpartyChannelID, version, proofInit, proofHeight, clientCtx.GetFromAddress(), ) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.ChannelOpenTry(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } @@ -139,11 +146,14 @@ func NewChannelOpenAckCmd() *cobra.Command { msg := types.NewMsgChannelOpenAck( portID, channelID, counterpartyChannelID, version, proofTry, proofHeight, clientCtx.GetFromAddress(), ) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.ChannelOpenAck(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } cmd.Flags().String(FlagIBCVersion, ibctransfertypes.Version, "IBC application version") @@ -179,11 +189,14 @@ func NewChannelOpenConfirmCmd() *cobra.Command { msg := types.NewMsgChannelOpenConfirm( portID, channelID, proofAck, proofHeight, clientCtx.GetFromAddress(), ) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.ChannelOpenConfirm(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } @@ -207,11 +220,14 @@ func NewChannelCloseInitCmd() *cobra.Command { channelID := args[1] msg := types.NewMsgChannelCloseInit(portID, channelID, clientCtx.GetFromAddress()) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.ChannelCloseInit(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } @@ -247,11 +263,14 @@ func NewChannelCloseConfirmCmd() *cobra.Command { msg := types.NewMsgChannelCloseConfirm( portID, channelID, proofInit, proofHeight, clientCtx.GetFromAddress(), ) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.ChannelCloseConfirm(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } diff --git a/x/params/client/cli/tx.go b/x/params/client/cli/tx.go index 39b0242522f4..f83793a1404c 100644 --- a/x/params/client/cli/tx.go +++ b/x/params/client/cli/tx.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/tx" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/version" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" paramscutils "github.com/cosmos/cosmos-sdk/x/params/client/utils" @@ -80,11 +81,14 @@ Where proposal.json contains: if err != nil { return err } - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := govtypes.NewMsgClient(svcMsgClientConn) + _, err = msgClient.SubmitProposal(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } } diff --git a/x/slashing/client/cli/tx.go b/x/slashing/client/cli/tx.go index d896c8570cf5..67a83e6a6510 100644 --- a/x/slashing/client/cli/tx.go +++ b/x/slashing/client/cli/tx.go @@ -7,6 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/x/slashing/types" ) @@ -41,11 +42,14 @@ $ tx slashing unjail --from mykey valAddr := clientCtx.GetFromAddress() msg := types.NewMsgUnjail(sdk.ValAddress(valAddr)) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.Unjail(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } diff --git a/x/staking/client/cli/tx.go b/x/staking/client/cli/tx.go index 10ceba6a45e0..b7cd500cfae8 100644 --- a/x/staking/client/cli/tx.go +++ b/x/staking/client/cli/tx.go @@ -13,6 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/tx" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -59,12 +60,19 @@ func NewCreateValidatorCmd() *cobra.Command { } txf := tx.NewFactoryCLI(clientCtx, cmd.Flags()).WithTxConfig(clientCtx.TxConfig).WithAccountRetriever(clientCtx.AccountRetriever) - txf, msg, err := NewBuildCreateValidatorMsg(clientCtx, txf, cmd.Flags()) + txf, msg, err := newBuildCreateValidatorMsg(clientCtx, txf, cmd.Flags()) if err != nil { return err } - return tx.GenerateOrBroadcastTxWithFactory(clientCtx, txf, msg) + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.CreateValidator(cmd.Context(), msg) + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxWithFactory(clientCtx, txf, svcMsgClientConn.GetMsgs()...) }, } @@ -128,11 +136,14 @@ func NewEditValidatorCmd() *cobra.Command { } msg := types.NewMsgEditValidator(sdk.ValAddress(valAddr), description, newRate, newMinSelfDelegation) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.EditValidator(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } @@ -177,11 +188,14 @@ $ %s tx staking delegate %s1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm 1000stake --f } msg := types.NewMsgDelegate(delAddr, valAddr, amount) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.Delegate(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } @@ -228,11 +242,14 @@ $ %s tx staking redelegate %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj %s1l2rsakp3 } msg := types.NewMsgBeginRedelegate(delAddr, valSrcAddr, valDstAddr, amount) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.BeginRedelegate(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } @@ -274,11 +291,14 @@ $ %s tx staking unbond %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj 100stake --from } msg := types.NewMsgUndelegate(delAddr, valAddr, amount) - if err := msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := types.NewMsgClient(svcMsgClientConn) + _, err = msgClient.Undelegate(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } @@ -287,7 +307,7 @@ $ %s tx staking unbond %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj 100stake --from return cmd } -func NewBuildCreateValidatorMsg(clientCtx client.Context, txf tx.Factory, fs *flag.FlagSet) (tx.Factory, sdk.Msg, error) { +func newBuildCreateValidatorMsg(clientCtx client.Context, txf tx.Factory, fs *flag.FlagSet) (tx.Factory, *types.MsgCreateValidator, error) { fAmount, _ := fs.GetString(FlagAmount) amount, err := sdk.ParseCoinNormalized(fAmount) if err != nil { diff --git a/x/staking/client/rest/query.go b/x/staking/client/rest/query.go index d515d5dfed9b..7fae344d6748 100644 --- a/x/staking/client/rest/query.go +++ b/x/staking/client/rest/query.go @@ -151,20 +151,30 @@ func delegatorTxsHandlerFn(clientCtx client.Context) http.HandlerFunc { actions []string ) + // For each case, we search txs for both: + // - legacy messages: their Type() is a custom string, e.g. "delegate" + // - service Msgs: their Type() is their FQ method name, e.g. "/cosmos.staking.v1beta1.Msg/Deledate" + // and we combine the results. switch { case isBondTx: - actions = append(actions, types.MsgDelegate{}.Type()) + actions = append(actions, types.TypeMsgDelegate) + actions = append(actions, types.TypeSvcMsgDelegate) case isUnbondTx: - actions = append(actions, types.MsgUndelegate{}.Type()) + actions = append(actions, types.TypeMsgUndelegate) + actions = append(actions, types.TypeSvcMsgUndelegate) case isRedTx: - actions = append(actions, types.MsgBeginRedelegate{}.Type()) + actions = append(actions, types.TypeMsgBeginRedelegate) + actions = append(actions, types.TypeSvcMsgBeginRedelegate) case noQuery: - actions = append(actions, types.MsgDelegate{}.Type()) - actions = append(actions, types.MsgUndelegate{}.Type()) - actions = append(actions, types.MsgBeginRedelegate{}.Type()) + actions = append(actions, types.TypeMsgDelegate) + actions = append(actions, types.TypeSvcMsgDelegate) + actions = append(actions, types.TypeMsgUndelegate) + actions = append(actions, types.TypeSvcMsgUndelegate) + actions = append(actions, types.TypeMsgBeginRedelegate) + actions = append(actions, types.TypeSvcMsgBeginRedelegate) default: w.WriteHeader(http.StatusNoContent) diff --git a/x/staking/types/msg.go b/x/staking/types/msg.go index 52ab1750b827..eda27b768a32 100644 --- a/x/staking/types/msg.go +++ b/x/staking/types/msg.go @@ -24,6 +24,13 @@ const ( TypeMsgCreateValidator = "create_validator" TypeMsgDelegate = "delegate" TypeMsgBeginRedelegate = "begin_redelegate" + + // These are used for querying events by action. + TypeSvcMsgUndelegate = "/cosmos.staking.v1beta1.Msg/Undelegate" + TypeSvcMsgEditValidator = "/cosmos.staking.v1beta1.Msg/EditValidator" + TypeSvcMsgCreateValidator = "/cosmos.staking.v1beta1.Msg/CreateValidator" + TypeSvcMsgDelegate = "/cosmos.staking.v1beta1.Msg/Deledate" + TypeSvcMsgBeginRedelegate = "/cosmos.staking.v1beta1.Msg/BeginRedelegate" ) var ( diff --git a/x/upgrade/client/cli/tx.go b/x/upgrade/client/cli/tx.go index 32472ad84d16..bb8382af03c4 100644 --- a/x/upgrade/client/cli/tx.go +++ b/x/upgrade/client/cli/tx.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/tx" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/x/gov/client/cli" gov "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/cosmos/cosmos-sdk/x/upgrade/types" @@ -69,11 +70,14 @@ func NewCmdSubmitUpgradeProposal() *cobra.Command { return err } - if err = msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := gov.NewMsgClient(svcMsgClientConn) + _, err = msgClient.SubmitProposal(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } @@ -128,11 +132,14 @@ func NewCmdSubmitCancelUpgradeProposal() *cobra.Command { return err } - if err = msg.ValidateBasic(); err != nil { + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + msgClient := gov.NewMsgClient(svcMsgClientConn) + _, err = msgClient.SubmitProposal(cmd.Context(), msg) + if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } From ef8dabcf0f2ecaf26db1c6c6d5922e9399458bb3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Feb 2021 19:47:51 +0000 Subject: [PATCH 148/152] build(deps): bump github.com/prometheus/common from 0.15.0 to 0.16.0 (#8619) Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.15.0 to 0.16.0. - [Release notes](https://github.com/prometheus/common/releases) - [Commits](https://github.com/prometheus/common/compare/v0.15.0...v0.16.0) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: SaReN --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 999997d9c68d..ea2011e8fbc9 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/pelletier/go-toml v1.8.1 // indirect github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.8.0 - github.com/prometheus/common v0.15.0 + github.com/prometheus/common v0.16.0 github.com/rakyll/statik v0.1.7 github.com/regen-network/cosmos-proto v0.3.1 github.com/rs/zerolog v1.20.0 diff --git a/go.sum b/go.sum index 3e0e029f13fb..0f376c9f1a70 100644 --- a/go.sum +++ b/go.sum @@ -561,8 +561,8 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.15.0 h1:4fgOnadei3EZvgRwxJ7RMpG1k1pOZth5Pc13tyspaKM= -github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.16.0 h1:VMiIg2fcMM+QkvAaPo6Hatk8OgpVHh4Yzp1+ljjjQAQ= +github.com/prometheus/common v0.16.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= From 0135a04f1bc2487c3edbf66356b07db0abc134a2 Mon Sep 17 00:00:00 2001 From: psaradev Date: Sat, 20 Feb 2021 00:28:31 +1000 Subject: [PATCH 149/152] add sr25519 keys sign algo --- crypto/hd/algo.go | 26 ++ crypto/keys/sr25519/keys.pb.go | 492 +++++++++++++++++++++++++ crypto/keys/sr25519/sr25519.go | 148 ++++++++ crypto/keys/sr25519/sr25519_nocgo.go | 15 + proto/cosmos/crypto/sr25519/keys.proto | 17 + 5 files changed, 698 insertions(+) create mode 100644 crypto/keys/sr25519/keys.pb.go create mode 100644 crypto/keys/sr25519/sr25519.go create mode 100644 crypto/keys/sr25519/sr25519_nocgo.go create mode 100644 proto/cosmos/crypto/sr25519/keys.proto diff --git a/crypto/hd/algo.go b/crypto/hd/algo.go index f934ad08aece..7ed908f3b6fa 100644 --- a/crypto/hd/algo.go +++ b/crypto/hd/algo.go @@ -4,7 +4,9 @@ import ( bip39 "github.com/cosmos/go-bip39" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/crypto/keys/sr25519" "github.com/cosmos/cosmos-sdk/crypto/types" + substratebip39 "github.com/sikkatech/go-substrate-bip39" ) // PubKeyType defines an algorithm to derive key-pairs which can be used for cryptographic signing. @@ -25,6 +27,8 @@ const ( var ( // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. Secp256k1 = secp256k1Algo{} + // Sr25519 represents the Sr25519Type signature system. + Sr25519 = sr25519Algo{} ) type DeriveFn func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) @@ -69,3 +73,25 @@ func (s secp256k1Algo) Generate() GenerateFn { return &secp256k1.PrivKey{Key: bzArr} } } + +type sr25519Algo struct { +} + +func (s sr25519Algo) Name() PubKeyType { + return Sr25519Type +} + +// Derive derives and returns the sr25519 private key for the given seed and HD path. +func (s sr25519Algo) Derive() DeriveFn { + return func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) { + seed, err := substratebip39.SeedFromMnemonic(mnemonic, bip39Passphrase) + return seed[:], err + } +} + +// Generate generates a sr25519 private key from the given bytes. +func (s sr25519Algo) Generate() GenerateFn { + return func(bz []byte) types.PrivKey { + return &sr25519.PrivKey{Key: bz} + } +} diff --git a/crypto/keys/sr25519/keys.pb.go b/crypto/keys/sr25519/keys.pb.go new file mode 100644 index 000000000000..e5d018bbe7ad --- /dev/null +++ b/crypto/keys/sr25519/keys.pb.go @@ -0,0 +1,492 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: crypto/sr25519/keys.proto + +package sr25519 + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// PubKey defines a sr25519 public key +type PubKey struct { + Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` +} + +func (m *PubKey) Reset() { *m = PubKey{} } +func (*PubKey) ProtoMessage() {} +func (*PubKey) Descriptor() ([]byte, []int) { + return fileDescriptor_da436b7df4d2f16b, []int{0} +} +func (m *PubKey) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PubKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PubKey.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 *PubKey) XXX_Merge(src proto.Message) { + xxx_messageInfo_PubKey.Merge(m, src) +} +func (m *PubKey) XXX_Size() int { + return m.Size() +} +func (m *PubKey) XXX_DiscardUnknown() { + xxx_messageInfo_PubKey.DiscardUnknown(m) +} + +var xxx_messageInfo_PubKey proto.InternalMessageInfo + +func (m *PubKey) GetKey() []byte { + if m != nil { + return m.Key + } + return nil +} + +// PrivKey defines a sr25519 private key. +type PrivKey struct { + Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` +} + +func (m *PrivKey) Reset() { *m = PrivKey{} } +func (m *PrivKey) String() string { return proto.CompactTextString(m) } +func (*PrivKey) ProtoMessage() {} +func (*PrivKey) Descriptor() ([]byte, []int) { + return fileDescriptor_da436b7df4d2f16b, []int{1} +} +func (m *PrivKey) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PrivKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PrivKey.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 *PrivKey) XXX_Merge(src proto.Message) { + xxx_messageInfo_PrivKey.Merge(m, src) +} +func (m *PrivKey) XXX_Size() int { + return m.Size() +} +func (m *PrivKey) XXX_DiscardUnknown() { + xxx_messageInfo_PrivKey.DiscardUnknown(m) +} + +var xxx_messageInfo_PrivKey proto.InternalMessageInfo + +func (m *PrivKey) GetKey() []byte { + if m != nil { + return m.Key + } + return nil +} + +func init() { + proto.RegisterType((*PubKey)(nil), "straightedge.crypto.PubKey") + proto.RegisterType((*PrivKey)(nil), "straightedge.crypto.PrivKey") +} + +func init() { proto.RegisterFile("crypto/sr25519/keys.proto", fileDescriptor_da436b7df4d2f16b) } + +var fileDescriptor_da436b7df4d2f16b = []byte{ + // 184 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0x2e, 0xaa, 0x2c, + 0x28, 0xc9, 0xd7, 0x2f, 0x2e, 0x32, 0x32, 0x35, 0x35, 0xb4, 0xd4, 0xcf, 0x4e, 0xad, 0x2c, 0xd6, + 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x2e, 0x2e, 0x29, 0x4a, 0xcc, 0x4c, 0xcf, 0x28, 0x49, + 0x4d, 0x49, 0x4f, 0xd5, 0x83, 0xa8, 0x93, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0xcb, 0xeb, 0x83, + 0x58, 0x10, 0xa5, 0x4a, 0x0a, 0x5c, 0x6c, 0x01, 0xa5, 0x49, 0xde, 0xa9, 0x95, 0x42, 0x02, 0x5c, + 0xcc, 0xd9, 0xa9, 0x95, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x3c, 0x41, 0x20, 0xa6, 0x15, 0xcb, 0x8c, + 0x05, 0xf2, 0x0c, 0x4a, 0xd2, 0x5c, 0xec, 0x01, 0x45, 0x99, 0x65, 0x58, 0x95, 0x38, 0x85, 0x9e, + 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, + 0x5c, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x75, 0x7a, 0x66, 0x49, 0x46, 0x69, + 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x46, 0x6a, 0x25, 0xb2, 0x8b, 0xf4, 0x51, 0x38, 0x50, 0x6f, + 0x80, 0x9c, 0x0f, 0xf3, 0x4b, 0x12, 0x1b, 0xd8, 0x71, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x8d, 0x58, 0x06, 0xce, 0xe4, 0x00, 0x00, 0x00, +} + +func (m *PubKey) 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 *PubKey) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PubKey) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Key) > 0 { + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintKeys(dAtA, i, uint64(len(m.Key))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *PrivKey) 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 *PrivKey) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PrivKey) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Key) > 0 { + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintKeys(dAtA, i, uint64(len(m.Key))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintKeys(dAtA []byte, offset int, v uint64) int { + offset -= sovKeys(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *PubKey) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Key) + if l > 0 { + n += 1 + l + sovKeys(uint64(l)) + } + return n +} + +func (m *PrivKey) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Key) + if l > 0 { + n += 1 + l + sovKeys(uint64(l)) + } + return n +} + +func sovKeys(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozKeys(x uint64) (n int) { + return sovKeys(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *PubKey) 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 ErrIntOverflowKeys + } + 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: PubKey: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PubKey: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowKeys + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthKeys + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthKeys + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...) + if m.Key == nil { + m.Key = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipKeys(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthKeys + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PrivKey) 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 ErrIntOverflowKeys + } + 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: PrivKey: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PrivKey: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowKeys + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthKeys + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthKeys + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...) + if m.Key == nil { + m.Key = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipKeys(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthKeys + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipKeys(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowKeys + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowKeys + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowKeys + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthKeys + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupKeys + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthKeys + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthKeys = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowKeys = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupKeys = fmt.Errorf("proto: unexpected end of group") +) diff --git a/crypto/keys/sr25519/sr25519.go b/crypto/keys/sr25519/sr25519.go new file mode 100644 index 000000000000..3c2f3a8b0a9d --- /dev/null +++ b/crypto/keys/sr25519/sr25519.go @@ -0,0 +1,148 @@ +package sr25519 + +import ( + "bytes" + "crypto/subtle" + "fmt" + "math/big" + + "github.com/tendermint/tendermint/crypto" + tmsr25519 "github.com/tendermint/tendermint/crypto/sr25519" + + // nolint: staticcheck // necessary for Bitcoin address format + "github.com/cosmos/cosmos-sdk/codec" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/types/errors" +) + +var _ cryptotypes.PrivKey = &PrivKey{} +var _ codec.AminoMarshaler = &PrivKey{} + +const ( + PrivKeySize = 32 + keyType = "sr25519" + PrivKeyName = "tendermint/PrivKeySr25519" + PubKeyName = "tendermint/PubKeySr25519" +) + +// Bytes returns the byte representation of the Private Key. +func (privKey *PrivKey) Bytes() []byte { + return privKey.Key +} + +// PubKey gets the corresponding public key from the private key. +func (privKey *PrivKey) PubKey() cryptotypes.PubKey { + return &PubKey{Key: tmsr25519.PrivKey(privKey.Key).PubKey().Bytes()} +} + +// Equals - you probably don't need to use this. +// Runs in constant time based on length of the +func (privKey *PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool { + return privKey.Type() == other.Type() && subtle.ConstantTimeCompare(privKey.Bytes(), other.Bytes()) == 1 +} + +func (privKey *PrivKey) Type() string { + return keyType +} + +// MarshalAmino overrides Amino binary marshalling. +func (privKey PrivKey) MarshalAmino() ([]byte, error) { + return privKey.Key, nil +} + +// UnmarshalAmino overrides Amino binary marshalling. +func (privKey *PrivKey) UnmarshalAmino(bz []byte) error { + if len(bz) != PrivKeySize { + return fmt.Errorf("invalid privkey size") + } + privKey.Key = bz + + return nil +} + +// MarshalAminoJSON overrides Amino JSON marshalling. +func (privKey PrivKey) MarshalAminoJSON() ([]byte, error) { + // When we marshal to Amino JSON, we don't marshal the "key" field itself, + // just its contents (i.e. the key bytes). + return privKey.MarshalAmino() +} + +// UnmarshalAminoJSON overrides Amino JSON marshalling. +func (privKey *PrivKey) UnmarshalAminoJSON(bz []byte) error { + return privKey.UnmarshalAmino(bz) +} + +// GenPrivKey generates a new sr25519 private key. +// It uses OS randomness in conjunction with the current global random seed +// in tendermint/libs/common to generate the private key. +func GenPrivKey() *PrivKey { + return &PrivKey{Key: tmsr25519.GenPrivKey().Bytes()} +} + +var one = new(big.Int).SetInt64(1) + +// GenPrivKeyFromSecret hashes the secret with SHA2, and uses +// that 32 byte output to create the private key. +// NOTE: secret should be the output of a KDF like bcrypt, +// if it's derived from user input. +func GenPrivKeyFromSecret(secret []byte) *PrivKey { + return &PrivKey{Key: tmsr25519.GenPrivKeyFromSecret(secret).Bytes()} +} + +//------------------------------------- + +var _ cryptotypes.PubKey = &PubKey{} +var _ codec.AminoMarshaler = &PubKey{} + +// PubKeySize is comprised of 32 bytes for one field element +// (the x-coordinate), plus one byte for the parity of the y-coordinate. +const PubKeySize = 33 + +// Address returns a Bitcoin style addresses: RIPEMD160(SHA256(pubkey)) +func (pubKey *PubKey) Address() crypto.Address { + return tmsr25519.PubKey(pubKey.Key).Address() +} + +// Bytes returns the pubkey byte format. +func (pubKey *PubKey) Bytes() []byte { + return pubKey.Key +} + +func (pubKey *PubKey) String() string { + return fmt.Sprintf("PubKeySr25519{%X}", pubKey.Key) +} + +func (pubKey *PubKey) Type() string { + return keyType +} + +func (pubKey *PubKey) Equals(other cryptotypes.PubKey) bool { + return pubKey.Type() == other.Type() && bytes.Equal(pubKey.Bytes(), other.Bytes()) +} + +// MarshalAmino overrides Amino binary marshalling. +func (pubKey PubKey) MarshalAmino() ([]byte, error) { + return pubKey.Key, nil +} + +// UnmarshalAmino overrides Amino binary marshalling. +func (pubKey *PubKey) UnmarshalAmino(bz []byte) error { + if len(bz) != PubKeySize { + return errors.Wrap(errors.ErrInvalidPubKey, "invalid pubkey size") + } + pubKey.Key = bz + + return nil +} + +// MarshalAminoJSON overrides Amino JSON marshalling. +func (pubKey PubKey) MarshalAminoJSON() ([]byte, error) { + // When we marshal to Amino JSON, we don't marshal the "key" field itself, + // just its contents (i.e. the key bytes). + return pubKey.MarshalAmino() +} + +// UnmarshalAminoJSON overrides Amino JSON marshalling. +func (pubKey *PubKey) UnmarshalAminoJSON(bz []byte) error { + return pubKey.UnmarshalAmino(bz) +} diff --git a/crypto/keys/sr25519/sr25519_nocgo.go b/crypto/keys/sr25519/sr25519_nocgo.go new file mode 100644 index 000000000000..fe3008bbdecd --- /dev/null +++ b/crypto/keys/sr25519/sr25519_nocgo.go @@ -0,0 +1,15 @@ +package sr25519 + +import ( + tmsr25519 "github.com/tendermint/tendermint/crypto/sr25519" +) + +// Sign produces a signature on the provided message. +func (privKey *PrivKey) Sign(msg []byte) ([]byte, error) { + return tmsr25519.PrivKey(privKey.Key).Sign(msg) +} + +// VerifySignature - verifies a signature +func (pubKey *PubKey) VerifySignature(msg []byte, sigStr []byte) bool { + return tmsr25519.PubKey(pubKey.Key).VerifySignature(msg, sigStr) +} diff --git a/proto/cosmos/crypto/sr25519/keys.proto b/proto/cosmos/crypto/sr25519/keys.proto new file mode 100644 index 000000000000..bc3e5a5ae892 --- /dev/null +++ b/proto/cosmos/crypto/sr25519/keys.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; +package straightedge.crypto; + +import "gogoproto/gogo.proto"; + +option go_package = "github.com/heystraightedge/straightedge/crypto/keys/sr25519"; + +// PubKey defines a sr25519 public key +message PubKey { + option (gogoproto.goproto_stringer) = false; + bytes key = 1; +} + +// PrivKey defines a sr25519 private key. +message PrivKey { + bytes key = 1; +} From af7a5d921c473b8bbb8dcafc24f3186bd90c48c9 Mon Sep 17 00:00:00 2001 From: psaradev Date: Sat, 20 Feb 2021 01:00:43 +1000 Subject: [PATCH 150/152] lint --- crypto/keys/sr25519/sr25519.go | 3 -- go.mod | 2 +- go.sum | 52 ++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/crypto/keys/sr25519/sr25519.go b/crypto/keys/sr25519/sr25519.go index 3c2f3a8b0a9d..1f39bb064a1b 100644 --- a/crypto/keys/sr25519/sr25519.go +++ b/crypto/keys/sr25519/sr25519.go @@ -9,7 +9,6 @@ import ( "github.com/tendermint/tendermint/crypto" tmsr25519 "github.com/tendermint/tendermint/crypto/sr25519" - // nolint: staticcheck // necessary for Bitcoin address format "github.com/cosmos/cosmos-sdk/codec" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/types/errors" @@ -79,8 +78,6 @@ func GenPrivKey() *PrivKey { return &PrivKey{Key: tmsr25519.GenPrivKey().Bytes()} } -var one = new(big.Int).SetInt64(1) - // GenPrivKeyFromSecret hashes the secret with SHA2, and uses // that 32 byte output to create the private key. // NOTE: secret should be the output of a KDF like bcrypt, diff --git a/go.mod b/go.mod index ea2011e8fbc9..bfa44778a47a 100644 --- a/go.mod +++ b/go.mod @@ -36,10 +36,10 @@ require ( github.com/rakyll/statik v0.1.7 github.com/regen-network/cosmos-proto v0.3.1 github.com/rs/zerolog v1.20.0 + github.com/sikkatech/go-substrate-bip39 v0.0.0-20191224085309-34f8034ee0a5 github.com/spf13/afero v1.3.4 // indirect github.com/spf13/cast v1.3.1 github.com/spf13/cobra v1.1.3 - github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.7.1 github.com/stretchr/testify v1.7.0 diff --git a/go.sum b/go.sum index 0f376c9f1a70..39507d0dc189 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,7 @@ cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqCl cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/99designs/keyring v1.1.3/go.mod h1:657DQuMrBZRtuL/voxVyiyb6zpMehlm5vLB9Qwrv904= github.com/99designs/keyring v1.1.6 h1:kVDC2uCgVwecxCk+9zoCt2uEL6dt+dfVzMvGgnVcIuM= github.com/99designs/keyring v1.1.6/go.mod h1:16e0ds7LGQQcT59QqkTg72Hh5ShM51Byv5PEmW6uoRU= github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= @@ -28,6 +29,8 @@ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbt github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/ChainSafe/go-schnorrkel v0.0.0-20191217051421-8f63573202b6/go.mod h1:/w/EhyNmwlP1/LTWy7XufwTUZRljuJmuwCvX9TeFqxI= +github.com/ChainSafe/go-schnorrkel v0.0.0-20191224001618-60bb676dd3e4/go.mod h1:+cafF2OKta2sUnPSHcPjZ0MDgwpxFspKAlP2sstJ0eQ= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= @@ -43,6 +46,7 @@ github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrU github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= github.com/Workiva/go-datastructures v1.0.52 h1:PLSK6pwn8mYdaoaCZEMsXBpBotr4HHn9abU0yMQt0NI= github.com/Workiva/go-datastructures v1.0.52/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -68,6 +72,7 @@ github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQ github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d/go.mod h1:icNx/6QdFblhsEjZehARqbNumymUT/ydwlLojFdv7Sk= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -77,6 +82,7 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0= +github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M= github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= @@ -123,6 +129,9 @@ github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cosmos/cosmos-sdk v0.34.4-0.20191221032601-0255540f231e/go.mod h1:eAsW0ukTzolBNamfJdL4pJreORO0t1o0N/O0V7TqjS8= +github.com/cosmos/ethermint v0.0.0-20190802135314-3f32f9ba8a1f/go.mod h1:3uorjbOIEOqbASxo/tR7bq2S3cf+yy5vWratMU4xY40= +github.com/cosmos/go-bip39 v0.0.0-20180618194314-52158e4697b8/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= @@ -165,6 +174,7 @@ github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbT github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dvsekhvalnov/jose2go v0.0.0-20180829124132-7f401d37b68a/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b h1:HBah4D48ypg3J7Np4N+HY/ZR76fx3HEUGxDU6Uk39oQ= github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= @@ -178,6 +188,9 @@ github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25/go.mod h1:hTr8 github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/etcd-io/bbolt v1.3.2/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/ethereum/go-ethereum v1.9.6/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY= github.com/ethereum/go-ethereum v1.9.23 h1:SIKhg/z4Q7AbvqcxuPYvMxf36che/Rq/Pp0IdYEkbtw= github.com/ethereum/go-ethereum v1.9.23/go.mod h1:JIfVb6esrqALTExdz9hRYvrP0xBDf6wCncIu1hNwHpM= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= @@ -192,6 +205,7 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= @@ -207,6 +221,7 @@ github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.6.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= @@ -243,6 +258,7 @@ github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= @@ -301,6 +317,7 @@ github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -349,6 +366,7 @@ github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -357,6 +375,7 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/heystraightedge/straightedge v0.0.0-20191221062532-299f5807bc89/go.mod h1:qapig38GVxoRWnBz5nvqugZD+jZxfFKpA0XF8/NJA1s= github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= @@ -488,11 +507,13 @@ github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXW github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= @@ -520,6 +541,7 @@ github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144T github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= @@ -553,6 +575,7 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= @@ -573,9 +596,12 @@ github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULU github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rakyll/statik v0.1.6/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= +github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20190704165056-9c2d0518ed81/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg= @@ -587,6 +613,7 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= @@ -604,6 +631,8 @@ github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa/go.mod h1:F7 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sikkatech/go-substrate-bip39 v0.0.0-20191224085309-34f8034ee0a5 h1:daNBIl8o+aq2aCpkFD8x9Zp/1lVhJVRUiOMVx1t9m3c= +github.com/sikkatech/go-substrate-bip39 v0.0.0-20191224085309-34f8034ee0a5/go.mod h1:cHnrb12pwXfPQMmKVQuJ87ITpiF51wAunGGF8rmR66s= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= @@ -619,11 +648,14 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.3.4 h1:8q6vk3hthlpb2SouZcnBVKboxWQWMDNF38bwholZrJc= github.com/spf13/afero v1.3.4/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= @@ -638,8 +670,11 @@ github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.5.0/go.mod h1:AkYRkVJF8TkSG/xet6PzXX+l39KhhXa2pdqVSxnTcn4= +github.com/spf13/viper v1.6.1/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= @@ -660,8 +695,10 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stumble/gorocksdb v0.0.3/go.mod h1:v6IHdFBXk5DJ1K4FZ0xi+eY737quiiBxYtSWXadLybY= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca h1:Ld/zXl5t4+D69SiV4JoN7kkfvJdOWlPpfxrzxpLMoUk= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= @@ -672,13 +709,20 @@ github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2 h1:crekJuQ57yIBDuKd3/dMJ github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2/go.mod h1:gBPw8WV2Erm4UGHlBRiM3zaEBst4bsuihmMCNQdgP/s= github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RMWx1aInLzndwxKalgi5rTqgfXxOxbEI= github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= +github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso= +github.com/tendermint/go-amino v0.15.1/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= +github.com/tendermint/iavl v0.12.4/go.mod h1:8LHakzt8/0G3/I8FUU0ReNx98S/EP6eyPJkAUvEXT/o= +github.com/tendermint/tendermint v0.32.1/go.mod h1:jmPDAKuNkev9793/ivn/fTBnfpA9mGBww8MPRNPNxnU= +github.com/tendermint/tendermint v0.32.8/go.mod h1:5/B1XZjNYtVBso8o1l/Eg4A0Mhu42lDcmftoQl95j/E= github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4= github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg= github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= github.com/tendermint/tendermint v0.34.7 h1:lvBJFNqpDuEzKfLZKtUXOL5dMOpqHonHlO6LCujyl6E= github.com/tendermint/tendermint v0.34.7/go.mod h1:JVuu3V1ZexOaZG8VJMRl8lnfrGw6hEB2TVnoUwKRbss= +github.com/tendermint/tm-db v0.1.1/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw= +github.com/tendermint/tm-db v0.2.0/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw= github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI= github.com/tendermint/tm-db v0.6.3 h1:ZkhQcKnB8/2jr5EaZwGndN4owkPsGezW2fSisS9zGbg= github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8= @@ -731,13 +775,16 @@ golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -792,7 +839,9 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190916140828-c8589233b77d/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -837,6 +886,7 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -914,6 +964,7 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -973,6 +1024,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= From 445e11dc432f7f99df1bc7c1ad194d0f6f679f16 Mon Sep 17 00:00:00 2001 From: psaradev Date: Sat, 20 Feb 2021 01:08:26 +1000 Subject: [PATCH 151/152] lint --- crypto/keys/sr25519/keys.pb.go | 40 +++++++++++++------------- proto/cosmos/crypto/sr25519/keys.proto | 4 +-- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/crypto/keys/sr25519/keys.pb.go b/crypto/keys/sr25519/keys.pb.go index e5d018bbe7ad..2b3288d30f7d 100644 --- a/crypto/keys/sr25519/keys.pb.go +++ b/crypto/keys/sr25519/keys.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: crypto/sr25519/keys.proto +// source: cosmos/crypto/sr25519/keys.proto package sr25519 @@ -31,7 +31,7 @@ type PubKey struct { func (m *PubKey) Reset() { *m = PubKey{} } func (*PubKey) ProtoMessage() {} func (*PubKey) Descriptor() ([]byte, []int) { - return fileDescriptor_da436b7df4d2f16b, []int{0} + return fileDescriptor_daddabaf35039fbd, []int{0} } func (m *PubKey) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -76,7 +76,7 @@ func (m *PrivKey) Reset() { *m = PrivKey{} } func (m *PrivKey) String() string { return proto.CompactTextString(m) } func (*PrivKey) ProtoMessage() {} func (*PrivKey) Descriptor() ([]byte, []int) { - return fileDescriptor_da436b7df4d2f16b, []int{1} + return fileDescriptor_daddabaf35039fbd, []int{1} } func (m *PrivKey) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -113,26 +113,26 @@ func (m *PrivKey) GetKey() []byte { } func init() { - proto.RegisterType((*PubKey)(nil), "straightedge.crypto.PubKey") - proto.RegisterType((*PrivKey)(nil), "straightedge.crypto.PrivKey") + proto.RegisterType((*PubKey)(nil), "cosmos.crypto.sr25519.PubKey") + proto.RegisterType((*PrivKey)(nil), "cosmos.crypto.sr25519.PrivKey") } -func init() { proto.RegisterFile("crypto/sr25519/keys.proto", fileDescriptor_da436b7df4d2f16b) } +func init() { proto.RegisterFile("cosmos/crypto/sr25519/keys.proto", fileDescriptor_daddabaf35039fbd) } -var fileDescriptor_da436b7df4d2f16b = []byte{ - // 184 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0x2e, 0xaa, 0x2c, - 0x28, 0xc9, 0xd7, 0x2f, 0x2e, 0x32, 0x32, 0x35, 0x35, 0xb4, 0xd4, 0xcf, 0x4e, 0xad, 0x2c, 0xd6, - 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x2e, 0x2e, 0x29, 0x4a, 0xcc, 0x4c, 0xcf, 0x28, 0x49, - 0x4d, 0x49, 0x4f, 0xd5, 0x83, 0xa8, 0x93, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0xcb, 0xeb, 0x83, - 0x58, 0x10, 0xa5, 0x4a, 0x0a, 0x5c, 0x6c, 0x01, 0xa5, 0x49, 0xde, 0xa9, 0x95, 0x42, 0x02, 0x5c, - 0xcc, 0xd9, 0xa9, 0x95, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x3c, 0x41, 0x20, 0xa6, 0x15, 0xcb, 0x8c, - 0x05, 0xf2, 0x0c, 0x4a, 0xd2, 0x5c, 0xec, 0x01, 0x45, 0x99, 0x65, 0x58, 0x95, 0x38, 0x85, 0x9e, - 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, - 0x5c, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x75, 0x7a, 0x66, 0x49, 0x46, 0x69, - 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x46, 0x6a, 0x25, 0xb2, 0x8b, 0xf4, 0x51, 0x38, 0x50, 0x6f, - 0x80, 0x9c, 0x0f, 0xf3, 0x4b, 0x12, 0x1b, 0xd8, 0x71, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x8d, 0x58, 0x06, 0xce, 0xe4, 0x00, 0x00, 0x00, +var fileDescriptor_daddabaf35039fbd = []byte{ + // 183 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x48, 0xce, 0x2f, 0xce, + 0xcd, 0x2f, 0xd6, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0x2f, 0x2e, 0x32, 0x32, 0x35, 0x35, + 0xb4, 0xd4, 0xcf, 0x4e, 0xad, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x85, 0xa8, + 0xd0, 0x83, 0xa8, 0xd0, 0x83, 0xaa, 0x90, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0xab, 0xd0, 0x07, + 0xb1, 0x20, 0x8a, 0x95, 0x14, 0xb8, 0xd8, 0x02, 0x4a, 0x93, 0xbc, 0x53, 0x2b, 0x85, 0x04, 0xb8, + 0x98, 0xb3, 0x53, 0x2b, 0x25, 0x18, 0x15, 0x18, 0x35, 0x78, 0x82, 0x40, 0x4c, 0x2b, 0x96, 0x19, + 0x0b, 0xe4, 0x19, 0x94, 0xa4, 0xb9, 0xd8, 0x03, 0x8a, 0x32, 0xcb, 0xb0, 0x2a, 0x71, 0xf2, 0x3a, + 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, + 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0x83, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, + 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0x98, 0x93, 0xc1, 0x94, 0x6e, 0x71, 0x4a, 0x36, 0xcc, 0xf5, + 0x20, 0x57, 0xc3, 0xbc, 0x90, 0xc4, 0x06, 0x76, 0x91, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x2a, + 0xf0, 0xa3, 0x3f, 0xe2, 0x00, 0x00, 0x00, } func (m *PubKey) Marshal() (dAtA []byte, err error) { diff --git a/proto/cosmos/crypto/sr25519/keys.proto b/proto/cosmos/crypto/sr25519/keys.proto index bc3e5a5ae892..db4bdea74dff 100644 --- a/proto/cosmos/crypto/sr25519/keys.proto +++ b/proto/cosmos/crypto/sr25519/keys.proto @@ -1,9 +1,9 @@ syntax = "proto3"; -package straightedge.crypto; +package cosmos.crypto.sr25519; import "gogoproto/gogo.proto"; -option go_package = "github.com/heystraightedge/straightedge/crypto/keys/sr25519"; +option go_package = "github.com/cosmos/cosmos-sdk/crypto/keys/sr25519"; // PubKey defines a sr25519 public key message PubKey { From 532cc533ab588938388ffd473784c5a27c3d8ce0 Mon Sep 17 00:00:00 2001 From: psaradev Date: Sat, 20 Feb 2021 01:15:27 +1000 Subject: [PATCH 152/152] remove unused var --- crypto/keys/sr25519/sr25519.go | 1 - 1 file changed, 1 deletion(-) diff --git a/crypto/keys/sr25519/sr25519.go b/crypto/keys/sr25519/sr25519.go index 1f39bb064a1b..2ad549c69e5d 100644 --- a/crypto/keys/sr25519/sr25519.go +++ b/crypto/keys/sr25519/sr25519.go @@ -4,7 +4,6 @@ import ( "bytes" "crypto/subtle" "fmt" - "math/big" "github.com/tendermint/tendermint/crypto" tmsr25519 "github.com/tendermint/tendermint/crypto/sr25519"